import React, { Dispatch, SetStateAction, useState } from "react";
import Modal from "components/Modal";
import { Text } from "components/Typography";
import { Pill } from "components/Pill";

import { MultistageForm } from "./MultistageForm";
import { MultistageModalCompletionStageProps } from "./MultistageModalCompletionStage";

import "./MultistageModalForm.scss";

/**
 * The properties of the multistage form
 *
 * @member {ReactElement<CompletionStageProps>} completionStage Display a completion stage before finishing the modal
 * @member {boolean} displayStageTitle Display the `title` property of the current form stage in the modal
 * @member {boolean} displayProgress Display the current stage in the the modal title
 * @member {FormSubmitCallback} onCancel An event handler fired when the form is cancelled
 * @member {FormSubmitCallback} onFinish An event handler fired on form submission
 * @member {boolean} loading Display loading interface components
 */
export interface MultistageModalFormProps {
  completionStage?: React.ReactElement<MultistageModalCompletionStageProps>;
  displayStageTitle?: boolean;
  displayProgress?: boolean;
  initialValues?: any;
  title?: string;
  onCancel: (/*values: any*/) => void;
  onFinish: (values: any) => any;
  setStageSetter?: (value: Dispatch<SetStateAction<number>>) => void;
}

/**
 * Creates a modal popup with multiple form stages, defined by the component's
 * children
 *
 * @param {MultistageModalFormProps} props The properties for the modal form
 * @returns {ReactElement<MultistageModalFormProps>} The multistage modal
 */
export const MultistageModalForm: React.FC<MultistageModalFormProps> = ({
  children,
  completionStage,
  displayStageTitle = true,
  displayProgress = true,
  initialValues,
  title = "",
  onFinish,
  onCancel,
  setStageSetter,
}) => {
  const [currentStage, setCurrentStage] = useState(1);
  const [currentTitle, setCurrentTitle] = useState("");

  const [isComplete, setIsComplete] = useState(false);
  const [completedFormValues, setCompletedFormValues] = useState<any>({});

  const onModalFormFinish = async (values: any) => {
    const finishedValues = await onFinish(values);

    setCompletedFormValues(finishedValues || values);
    setIsComplete(true);
  };

  const onStageChange = (stage: number, props: any) => {
    setCurrentTitle(props.title || title);
    setCurrentStage(stage);
  };

  // Build the title element if required
  const childCount = React.Children.count(children);
  const titleElement = React.useMemo(
    () => (
      <React.Fragment>
        {displayStageTitle && currentTitle && (
          <Text className="multistage-form--title">{currentTitle}</Text>
        )}
        {displayProgress && (
          <Pill className="multistage-form--title-stage">
            {isComplete ? "Completed" : `Step ${currentStage}/${childCount}`}
          </Pill>
        )}
      </React.Fragment>
    ),
    [
      currentTitle,
      currentStage,
      childCount,
      displayProgress,
      displayStageTitle,
      isComplete,
      title,
    ]
  );

  // Hydrate the completion stage with the appropriate props
  const hydratedCompletionStage = React.useMemo(
    () =>
      completionStage &&
      React.cloneElement<MultistageModalCompletionStageProps>(completionStage, {
        ...completedFormValues,
        onCancel,
      }),
    [completionStage, completedFormValues, onCancel]
  );

  return (
    <Modal
      width={960}
      title={titleElement}
      visible={true}
      getContainer={false}
      zIndex={100}
      onCancel={onCancel}
    >
      {isComplete && completionStage ? (
        hydratedCompletionStage
      ) : (
        <MultistageForm
          initialValues={initialValues}
          onCancel={onCancel}
          onFinish={onModalFormFinish}
          onStageChange={onStageChange}
          setStageSetter={setStageSetter}
        >
          {children}
        </MultistageForm>
      )}
    </Modal>
  );
};
