import React, { useState } from 'react';
import { IStepFormHandle, IWizardData, wizardContext } from './form';

const StepController: React.FunctionComponent<{
  current: number;
  total: number;
  onNext: () => Promise<void>;
  onPrev: () => void;
}> = ({ current, total, onNext, onPrev }) => {
  return (
    <div className="step-control-container">
      <button
        disabled={current === 0}
        className="step-control"
        onClick={onPrev}
      >
        上一步
      </button>
      <button className="step-control" onClick={onNext}>
        {current === total - 1 ? '构建' : '下一步'}
      </button>
    </div>
  );
};

interface IStepConf {
  key: string;
  title: string;
}

type IRegister = (
  config: IStepConf
) => {
  key: string;
  formRef: React.RefCallback<IStepFormHandle<any>>;
};

export const Wizard: React.VoidFunctionComponent<{
  children: (register: IRegister) => React.ReactElement[];
  onFinish: (wizardData: IWizardData) => void;
}> = ({ children, onFinish }) => {
  const [currentStep, setCurrentStep] = useState(0);
  const [wizardData, setWizardData] = useState<IWizardData>({});

  const confs: IStepConf[] = [];
  const refs: { [key: string]: IStepFormHandle<any> | null | undefined } = {};

  const register: IRegister = conf => {
    confs.push(conf);
    const { key } = conf;
    return {
      key,
      formRef: h => (refs[key] = h)
    };
  };

  const forms = children(register);
  const currentKey = confs[currentStep].key;
  const totalSteps = confs.length;

  const onNext = async () => {
    const formData = await refs[currentKey]?.getData();
    if (!formData) {
      return;
    }
    const newData = { ...wizardData, [currentKey]: formData };
    setWizardData(newData);

    if (currentStep === totalSteps - 1) {
      onFinish(newData);
    } else {
      setCurrentStep(currentStep + 1);
    }
  };

  const stepHeaderItems = confs.map(({ key, title }, idx) => {
    return (
      <li key={key} className={currentStep === idx ? 'step-active' : ''}>
        <div className="step-index-item">
          <div className="step-index-label">{idx + 1}</div>
        </div>
        <div className="step-index-desc">{`步骤${idx + 1}: ${title}`}</div>
      </li>
    );
  });

  const steps = forms.map((form, idx) => (
    <div
      key={confs[idx].key}
      className={
        'step-content-form ' + (currentStep === idx ? 'step-active' : '')
      }
    >
      {form}
    </div>
  ));

  return (
    <div className="sync-wizard">
      <ul className="step-index-list">{stepHeaderItems}</ul>
      <div className="step-content-container">
        <wizardContext.Provider value={wizardData}>
          {steps}
        </wizardContext.Provider>
      </div>
      <StepController
        current={currentStep}
        total={totalSteps}
        onPrev={() => setCurrentStep(currentStep - 1)}
        onNext={onNext}
      />
    </div>
  );
};
