= (props) => {
  const { t } = useTranslation();
  let result = {t('operationDialog.error')}
;
  if (props.error != null) {
    result = (
      <>
        {result}
        {props.error}
      >
    );
  }
  return result;
};
export type OperationInputOptionalError = undefined | null | string;
export interface OperationInputErrorInfo {
  [index: number]: OperationInputOptionalError;
}
export type OperationInputValidator = (
  value: TValue,
  values: (string | boolean)[]
) => OperationInputOptionalError | OperationInputErrorInfo;
export interface OperationTextInputInfo {
  type: 'text';
  password?: boolean;
  label?: string;
  initValue?: string;
  textFieldProps?: Omit<
    React.InputHTMLAttributes,
    'type' | 'value' | 'onChange'
  >;
  helperText?: string;
  validator?: OperationInputValidator;
}
export interface OperationBoolInputInfo {
  type: 'bool';
  label: string;
  initValue?: boolean;
}
export interface OperationSelectInputInfoOption {
  value: string;
  label: string;
  icon?: React.ReactElement;
}
export interface OperationSelectInputInfo {
  type: 'select';
  label: string;
  options: OperationSelectInputInfoOption[];
  initValue?: string;
}
export type OperationInputInfo =
  | OperationTextInputInfo
  | OperationBoolInputInfo
  | OperationSelectInputInfo;
interface OperationResult {
  type: 'success' | 'failure';
  data: unknown;
}
interface OperationDialogProps {
  open: boolean;
  close: () => void;
  title: React.ReactNode;
  titleColor?: 'default' | 'dangerous' | 'create' | string;
  onProcess: (inputs: (string | boolean)[]) => Promise;
  inputScheme?: OperationInputInfo[];
  inputPrompt?: string | (() => React.ReactNode);
  processPrompt?: () => React.ReactNode;
  successPrompt?: (data: unknown) => React.ReactNode;
  failurePrompt?: (error: unknown) => React.ReactNode;
  onSuccessAndClose?: () => void;
}
const OperationDialog: React.FC = (props) => {
  const inputScheme = props.inputScheme ?? [];
  const { t } = useTranslation();
  type Step = 'input' | 'process' | OperationResult;
  const [step, setStep] = useState('input');
  const [values, setValues] = useState<(boolean | string)[]>(
    inputScheme.map((i) => {
      if (i.type === 'bool') {
        return i.initValue ?? false;
      } else if (i.type === 'text' || i.type === 'select') {
        return i.initValue ?? '';
      } else {
        throw new UiLogicError('Unknown input scheme.');
      }
    })
  );
  const [inputError, setInputError] = useState({});
  const close = (): void => {
    if (step !== 'process') {
      props.close();
      if (
        typeof step === 'object' &&
        step.type === 'success' &&
        props.onSuccessAndClose
      ) {
        props.onSuccessAndClose();
      }
    } else {
      console.log('Attempt to close modal when processing.');
    }
  };
  const onConfirm = (): void => {
    setStep('process');
    props.onProcess(values).then(
      (d: unknown) => {
        setStep({
          type: 'success',
          data: d,
        });
      },
      (e: unknown) => {
        setStep({
          type: 'failure',
          data: e,
        });
      }
    );
  };
  let body: React.ReactNode;
  if (step === 'input') {
    let inputPrompt =
      typeof props.inputPrompt === 'function'
        ? props.inputPrompt()
        : props.inputPrompt;
    inputPrompt = {inputPrompt}
;
    const updateValue = (
      index: number,
      newValue: string | boolean
    ): (string | boolean)[] => {
      const oldValues = values;
      const newValues = oldValues.slice();
      newValues[index] = newValue;
      setValues(newValues);
      return newValues;
    };
    const testErrorInfo = (errorInfo: OperationInputErrorInfo): boolean => {
      for (let i = 0; i < inputScheme.length; i++) {
        if (inputScheme[i].type === 'text' && errorInfo[i] != null) {
          return true;
        }
      }
      return false;
    };
    const calculateError = (
      oldError: OperationInputErrorInfo,
      index: number,
      newError: OperationInputOptionalError | OperationInputErrorInfo
    ): OperationInputErrorInfo => {
      if (newError === undefined) {
        return oldError;
      } else if (newError === null || typeof newError === 'string') {
        return { ...oldError, [index]: newError };
      } else {
        const newInputError: OperationInputErrorInfo = { ...oldError };
        for (const [index, error] of Object.entries(newError)) {
          if (error !== undefined) {
            newInputError[+index] = error as OperationInputOptionalError;
          }
        }
        return newInputError;
      }
    };
    const validateAll = (): boolean => {
      let newInputError = inputError;
      for (let i = 0; i < inputScheme.length; i++) {
        const item = inputScheme[i];
        if (item.type === 'text') {
          newInputError = calculateError(
            newInputError,
            i,
            item.validator?.(values[i] as string, values)
          );
        }
      }
      const result = !testErrorInfo(newInputError);
      setInputError(newInputError);
      return result;
    };
    body = (
      <>
        
          {inputPrompt}
          {inputScheme.map((item, index) => {
            const value = values[index];
            const error: string | undefined = ((e) =>
              typeof e === 'string' ? t(e) : undefined)(inputError?.[index]);
            if (item.type === 'text') {
              return (
                
                  {item.label && }
                   {
                      const v = e.target.value;
                      const newValues = updateValue(index, v);
                      setInputError(
                        calculateError(
                          inputError,
                          index,
                          item.validator?.(v, newValues)
                        )
                      );
                    }}
                    invalid={error != null}
                    {...item.textFieldProps}
                  />
                  {error != null && {error}}
                  {item.helperText && {t(item.helperText)}}
                
              );
            } else if (item.type === 'bool') {
              return (
                
                   {
                      updateValue(
                        index,
                        (e.target as HTMLInputElement).checked
                      );
                    }}
                  />
                  
                
              );
            } else if (item.type === 'select') {
              return (
                
                  
                   {
                      updateValue(index, event.target.value);
                    }}
                  >
                    {item.options.map((option, i) => {
                      return (
                        
                      );
                    })}
                  
                
              );
            }
          })}
        
        
          
          
        
      >
    );
  } else if (step === 'process') {
    body = (
      
        {props.processPrompt?.() ?? }
      
    );
  } else {
    let content: React.ReactNode;
    const result = step;
    if (result.type === 'success') {
      content =
        props.successPrompt?.(result.data) ?? t('operationDialog.success');
      if (typeof content === 'string')
        content = {content}
;
    } else {
      content = props.failurePrompt?.(result.data) ?? ;
      if (typeof content === 'string')
        content = ;
    }
    body = (
      <>
        {content}
        
          
        
      >
    );
  }
  const title = typeof props.title === 'string' ? t(props.title) : props.title;
  return (
    
      
        {title}
      
      {body}
    
  );
};
export default OperationDialog;