// This file is part of Invenio-RDM-Records
// Copyright (C) 2020-2023 CERN.
// Copyright (C) 2020-2022 Northwestern University.
// Copyright (C) 2021 Graz University of Technology.
//
// Invenio-RDM-Records is free software; you can redistribute it and/or modify it
// under the terms of the MIT License; see LICENSE file for more details.

import React, { Component } from "react";
import PropTypes from "prop-types";
import { getIn, FieldArray } from "formik";
import { Button, Form, Label, List, Icon } from "semantic-ui-react";
import _get from "lodash/get";
import _truncate from "lodash/truncate";
import { FieldLabel } from "react-invenio-forms";
import { HTML5Backend } from "react-dnd-html5-backend";
import { DndProvider } from "react-dnd";
import { RelatedItemsModal } from "./RelatedItemsModal";
import { RelatedItemsFieldItem } from "./RelatedItemsFieldItem";
import { i18next } from "@translations/nr/i18next";

const relatedItemNameDisplay = (value) => {
  const name = _get(value, `itemTitle`);
  const URL = _get(value, `itemURL`);
  return (
    <span>
      {name}
      <a style={{ paddingLeft: "3rem" }} href={URL}>
        {URL && _truncate(URL, { length: 40, omission: "..." })}
      </a>
    </span>
  );
};

class RelatedItemsFieldForm extends Component {
  handleRelatedItemChange = (selectedRelatedItem) => {
    const { push: formikArrayPush } = this.props;
    formikArrayPush(selectedRelatedItem);
  };

  render() {
    const {
      form: { values, errors, initialErrors, initialValues },
      remove: formikArrayRemove,
      replace: formikArrayReplace,
      move: formikArrayMove,
      fieldPath,
      label,
      labelIcon,
      modal,
      addButtonLabel,
      required,
      helpText,
    } = this.props;

    const relatedItemsList = getIn(values, fieldPath, []);
    const formikInitialValues = getIn(initialValues, fieldPath, []);

    const error = getIn(errors, fieldPath, null);
    const initialError = getIn(initialErrors, fieldPath, null);
    const relatedItemsError =
      error || (relatedItemsList === formikInitialValues && initialError);

    return (
      <DndProvider backend={HTML5Backend}>
        <Form.Field
          required={required}
          className={relatedItemsError ? "error" : ""}
        >
          <FieldLabel htmlFor={fieldPath} icon={labelIcon} label={label} />
          <label className="helptext">{helpText}</label>
          <List>
            {relatedItemsList.map((value, index) => {
              const key = `${fieldPath}.${index}`;
              const displayName = relatedItemNameDisplay(value);
              return (
                <RelatedItemsFieldItem
                  key={key}
                  displayName={displayName}
                  index={index}
                  compKey={key}
                  initialRelatedItem={value}
                  removeRelatedItem={formikArrayRemove}
                  replaceRelatedItem={formikArrayReplace}
                  moveRelatedItem={formikArrayMove}
                  addLabel={modal.addLabel}
                  editLabel={modal.editLabel}
                />
              );
            })}
            <RelatedItemsModal
              onRelatedItemChange={this.handleRelatedItemChange}
              initialAction="add"
              addLabel={modal.addLabel}
              editLabel={modal.editLabel}
              trigger={
                <Button type="button" icon labelPosition="left">
                  <Icon name="add" />
                  {addButtonLabel}
                </Button>
              }
            />

            {relatedItemsError && typeof relatedItemsError == "string" && (
              <Label pointing="left" prompt>
                {relatedItemsError}
              </Label>
            )}
          </List>
        </Form.Field>
      </DndProvider>
    );
  }
}

export class RelatedItemsField extends Component {
  render() {
    const { fieldPath } = this.props;

    return (
      <FieldArray
        name={fieldPath}
        component={(formikProps) => (
          <RelatedItemsFieldForm {...formikProps} {...this.props} />
        )}
      />
    );
  }
}

RelatedItemsFieldForm.propTypes = {
  fieldPath: PropTypes.string.isRequired,
  addButtonLabel: PropTypes.string,
  modal: PropTypes.shape({
    addLabel: PropTypes.string.isRequired,
    editLabel: PropTypes.string.isRequired,
  }),
  label: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
  labelIcon: PropTypes.string,
  form: PropTypes.object.isRequired,
  remove: PropTypes.func.isRequired,
  replace: PropTypes.func.isRequired,
  move: PropTypes.func.isRequired,
  push: PropTypes.func.isRequired,
  required: PropTypes.bool,
  helpText: PropTypes.string,
};

RelatedItemsFieldForm.defaultProps = {
  label: i18next.t("Related items"),
  modal: {
    addLabel: i18next.t("Add related item"),
    editLabel: i18next.t("Edit related item"),
  },
  addButtonLabel: i18next.t("Add related item"),
  helpText: i18next.t(
    "Write down information about a resource related to the resource being described (i.e. if you are describing an article, here you can identify a magazine in which the article was published)."
  ),
};

RelatedItemsField.propTypes = {
  fieldPath: PropTypes.string.isRequired,
  addButtonLabel: PropTypes.string,
  modal: PropTypes.shape({
    addLabel: PropTypes.string,
    editLabel: PropTypes.string,
  }),

  label: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
  labelIcon: PropTypes.string,
  required: PropTypes.bool,
};

RelatedItemsField.defaultProps = {
  label: undefined,
  labelIcon: undefined,
  modal: {
    addLabel: i18next.t("Add related item"),
    editLabel: i18next.t("Edit related item"),
  },
  addButtonLabel: i18next.t("Add related item"),
};
