import * as React from "react";
import * as moment from "moment";
import MagaMultiProgressBar from "../maga-multi-progress-bar";
import DatePicker, { registerLocale } from "react-datepicker";
// @ts-ignore
import MultiSelect from "@kenshooui/react-multi-select";
import ptBr from "date-fns/locale/pt-BR";
registerLocale("pt-BR", ptBr);

import "moment/locale/pt-br";

import { DatesRangeInput } from "semantic-ui-calendar-react";
import {
  Accordion,
  Button,
  Divider,
  Dropdown,
  Header,
  Icon,
  Label,
  Popup,
  Segment,
  Radio,
  Checkbox as CheckboxSemantic,
  Search,
  Grid,
} from "semantic-ui-react";

const ReactInputMask = require("react-input-mask");
const cloneDeep = require("clone-deep");
import { Picky } from "react-picky";
const { Form, Checkbox, RadioGroup } = require("formsy-semantic-ui-react");

interface Row {
  row: {
    grouped?: boolean;
    groupedCopy?: boolean;
    removed?: boolean;
    groupName?: string;
    fields: Field[];
  };
}

interface Field {
  label: string;
  name: string;
  type: string;
  value?: string;
  placeholder?: string;
  maxLength?: number;
  mask?: string;
  maskChar?: string;
  required?: boolean;
  disabled?: boolean;
  validations?: object;
  validationErrors?: object;
  width: number;
  data?: any[];
  multiple?: boolean;
  defaultChecked?: boolean;
  position?: number;
  grouped?: boolean;
  handleChange?: any;
}

interface Props {
  /** Título fdo formulário */
  title?: string;
  /** Objeto de retorno com todos valores do formulário no submit */
  onSubmit?: ((data: {}) => void) | any;
  /** Objeto de retorno com todos valores do formulário no onChange */
  onChange?: ((data: {}) => void) | any;
  /** Objeto de retorno com todos valores do formulário no onChange */
  onBlur?: ((data: {}) => void) | any;
  /** Coleção da definição dos campos do formulário */
  formTemplate: Row[];
  /** Tipo de borda do formulário */
  border?: "attached" | "segment";
  /** Loading do formulário */
  loading?: boolean;
  /** Referência do formulário */
  refForm?: string;
  /** Formulário em com modo accordion */
  accordion?: boolean;
  /** Estado inicial do accordion do formulário */
  accordionOpened?: boolean;
  /** Estado atual do accordion do formulário */
  accordionStatusOpened?: any;
  /** Componente superior a direita do form */
  actionRightTop?: any;
  /** Add children no final do Segment */
  children?: any;
}
interface State {
  formState: any;
  multiSelect: any[];
  formTemplate: Row[];
  count: number;
  activeAccordion: boolean | undefined;
}

const errorLabel = <Label color="red" pointing />;
const errorLabelRadio = <Label color="red" pointing="left" />;
const INPUT_VARIATIONS = {
  TOGGLE: "toggle",
  SLIDER: "slider",
  CHECKBOX: "checkbox",
};

export default class MagaForm extends React.Component<Props, State> {
  private form: any;
  static defaultProps = {
    title: "",
    formTemplate: [],
    border: null,
    loading: false,
    refForm: "mainForm",
    accordion: true,
    accordionOpened: true,
    accordionStatusOpened: () => false,
    onChange: () => false,
    onBlur: () => false,
  };

  constructor(props: Props) {
    super(props);
    const formState = this.getInitialFormState();
    this.state = {
      formState,
      multiSelect: [],
      formTemplate: this.props.formTemplate,
      count: this.props.formTemplate.length,
      activeAccordion: this.props.accordionOpened,
    };
    this.form = React.createRef();
    this.resetForm = this.resetForm.bind(this);
  }

  componentDidMount() {
    const { formState } = this.state;
    const fieldsDateRange = this.props.formTemplate.find((element: any) => {
      return element.row.fields.find(
        (field: any) => field.type === "dateRange"
      );
    });
    if (fieldsDateRange) {
      fieldsDateRange.row.fields.forEach((field: any) => {
        formState[field.name] = field.defaultValue;
      });
      this.setState({
        formState,
      });
    }
  }

  UNSAFE_componentWillReceiveProps(props: any) {
    const { formTemplate } = this.props;
    this.setState({
      formTemplate: formTemplate,
    });
  }

  resetForm() {
    this.form.reset();
    let formTemplate = this.resetCompNotNative(this.state.formTemplate);
    formTemplate = formTemplate.filter((item: any) => !item.row.groupedCopy);
    let formState = this.getInitialFormState();

    const boolStates = Object.keys(this.state.formState)
      .filter((key) => typeof formState[key] === "boolean")
      .map((key) => ({ [key]: formState[key] }));

    if (boolStates.length) {
      formState = boolStates.reduce((a, b) => ({ ...a, ...b }));
    }

    this.setState({ formState, formTemplate });
  }

  getInitialFormState = () =>
    this.props.formTemplate.reduce((totalFields: any, item: any) => {
      if (item.row.fields) {
        return item.row.fields.reduce((rowFields: any, field: any) => {
          if (field.type === "select") {
            return {
              ...rowFields,
              [field.name]: cloneDeep(field.defaultData),
            };
          }
          return rowFields;
        }, totalFields);
      }
      return totalFields;
    }, {});

  resetCompNotNative(formTemplate: any) {
    const x = formTemplate.filter((item: any) => !item.row.groupedCopy);
    x.forEach((item: any) => {
      item.row.fields
        .filter((field: any) => field.type === "multiSelectArea" || field.mask)
        .forEach((field: any) => {
          field.defaultData = [];
          field.defaultValue = "";
        });
    });
    return x;
  }

  resetUpdate(obj: any) {
    this.form.reset(obj);
  }

  handleChangeMultSelectArea(values: any) {
    const formState = this.state.formState;
    formState["name"] = values;
    this.setState({
      formState: formState,
    });
  }

  addRows(rows: any) {
    let formTemplate = this.state.formTemplate;
    formTemplate.length = 3;
    formTemplate = formTemplate.concat(rows);
    this.setState({
      formTemplate: formTemplate,
    });
  }

  createRows(rows: any) {
    let formTemplate = this.state.formTemplate;
    formTemplate = formTemplate.concat(rows);
    this.setState({
      formTemplate: formTemplate,
    });
  }

  keepRows(upTo: number) {
    let formTemplate = this.state.formTemplate;
    formTemplate.length = upTo;
    this.setState({
      formTemplate: formTemplate,
    });
  }

  handleChange = (e: any, { name, value }: any) => {
    const formState = this.state.formState;
    formState[name] = value;
    this.setState({
      formState: formState,
    });
    this.props.onChange({ [name]: value });
  };

  handleChangeSelect = (
    name: any,
    handleChange: any,
    indexRow: number,
    indexField: number,
    e: any,
    data: any
  ) => {
    const { value } = data;
    let formState = this.state.formState;
    const formTemplate = cloneDeep(this.state.formTemplate);
    const fields = formTemplate[indexRow].row.fields;
    const { grouped, uniquePerGroup, multiple, data: fieldData } = fields[
      indexField
    ];
    const allData = uniquePerGroup
      ? fields.reduce((accumulator: any, field: any) => {
          const newData = field.data.filter(
            ({ value: fieldValue }: any) =>
              !accumulator.find(
                ({ value: accValue }: any) => fieldValue === accValue
              )
          );
          return [...accumulator, ...newData];
        }, [])
      : fieldData;
    const fieldValues = multiple
      ? value.map((valueId: any) => {
          const completeValue = allData.find(
            (item: any) => item.value === valueId
          );
          return completeValue;
        }, [])
      : allData.find((item: any) => item.value === value);
    formState[name] = fieldValues;

    let aditionalArguments: any[] = [];
    if (grouped && uniquePerGroup) {
      aditionalArguments.push({});
      const unusedData = fields.reduce((remaningData: any, field: any) => {
        const fieldData = formState[field.name];
        return remaningData.filter((remainingDataItem: any) => {
          const isValueUsed = fieldData.some(
            (fieldDataItem: any) => remainingDataItem.key === fieldDataItem.key
          );
          return !isValueUsed;
        });
      }, allData);
      fields.forEach((field: any) => {
        field.defaultData = formState[field.name];
        field.data = [...formState[field.name], ...unusedData];
        const groupedValues = aditionalArguments[aditionalArguments.length - 1];
        groupedValues[field.name] = field.defaultData;
      });
      formTemplate[indexRow].row.fields = fields;
    }

    this.setState({
      formTemplate,
      formState,
    });
    const fieldValue = { [name]: fieldValues };
    this.props.onChange(fieldValue, ...aditionalArguments);
    if (handleChange) {
      handleChange(e, data, fieldValue, ...aditionalArguments);
    }
  };

  handleChangeMultSelect = (name: any, value: any, e: any) => {
    let formState = this.state.formState;
    formState[name] = value;
    this.setState({
      formState: formState,
    });
    this.props.onChange({ [name]: value });
  };

  handleChangeDateChange = (name: any, value: any, e: any) => {
    let formState = this.state.formState;
    formState[name] = value;
    this.setState({
      formState: formState,
    });
    this.props.onChange({ [name]: value });
  };

  handleCheckboxChange = (name: any, e: any, input: any) => {
    const formState = this.state.formState;
    formState[name] = input.checked;
    this.setState({ formState });
    this.props.onChange({ [name]: input.checked });
  };

  handleChangeDropdown = (name: any, e: any, input: any) => {
    let formState = this.state.formState;
    formState[name] = input.value;
    this.setState({
      formState: formState,
    });
    this.props.onChange({ [name]: input.value });
  };

  handleChangeInput = (name: any, e: any) => {
    const formState = this.state.formState;
    formState[name] = e.target.value;
    this.setState({
      formState: formState,
    });
    this.props.onChange({ [name]: e.target.value });
  };

  handleBlurInput = ({ target: { value, name } }: any) => {
    this.props.onBlur({ [name]: value });
  };

  handleChangeInputMask = ({ target: { value, name } }: any) => {
    const formState = this.state.formState;
    formState[name] = value;
    this.setState({
      formState: formState,
    });
    this.props.onChange({ [name]: value });
  };

  updateField = ({ name, value }: any) => {
    const formState = this.state.formState;
    formState[name] = value;
    this.setState({
      formState: formState,
    });
  };

  /*
  handleChangeInputMask = (input: any, e: any) => {
    
    const formState = this.state.formState;
    // caso seja raw, remover a máscara
    if (input.raw) {
      e.target.value = e.target.value && e.target.value.replace(/[^0-Z]+/g, "");
    }

    if (e.target.value) {
      // caso o valor não seja vazio, seto o valor
      // se for raw, o valor vai com a máscara, caso contrário, a máscara já foi removida acima
      formState[input.name] = e.target.value;
    } else {
      // se o valor anterior do input ou o valor anterior sem a máscara for vazio ou se tinha apenas um caractere
      // isso significa que o usuário apagou tudo de uma vez, ou apagou caractere a caractere
      // entao seto o defaultValue para null, para limpar o input, caso contrário sempre ficaria preenchido com o defaultValue
      if (
        !formState[input.name] ||
        !formState[input.name].replace(/[^0-Z]+/g, "") ||
        formState[input.name].length === 1
      ) {
        input.defaultValue = null;
      }
      formState[input.name] = null;
    }
    this.setState({
      formState: formState,
    });
    
  };
*/

  onValidSubmit = (formData: any) => {
    formData = this.mountFormData(formData);
    const formState = this.state.formState;
    const allData = (Object as any).assign({}, formData, formState);
    this.props.onSubmit(allData);
  };

  mountFormData(formData: any) {
    const formTemplate = this.state.formTemplate;
    const formTemplateFiltered = formTemplate
      .filter((item: any) => item.row.fields)
      .filter((item: any) => item.row.grouped);
    if (formTemplateFiltered.length > 0) {
      let grouping: any = [];
      formTemplate
        .filter((item) => item.row.fields)
        .filter((item) => item.row.grouped)
        .filter((item) => !item.row.removed)
        .forEach((item: any) => {
          let rowCurrent: any = {};
          item.row.fields
            .filter((key: any) => key.name)
            .forEach((key: any) => {
              rowCurrent[key.name.split("_").shift()] = formData[key.name];
              item.row.id ? (rowCurrent.id = item.row.id) : false;
              delete formData[key.name];
            });
          grouping.push(rowCurrent);
        });

      formTemplateFiltered.forEach((item: any) => {
        item.row.fields
          .filter((key: any) => key.name)
          .forEach((key: any) => {
            delete formData[key.name];
          });
      });
      const groupName: any = formTemplateFiltered[0].row.groupName;
      formData[groupName] = grouping;
    }
    return formData;
  }

  addGrouping = (indexRow: number, indexField: number) => {
    const formTemplate = cloneDeep(this.state.formTemplate);
    formTemplate[indexRow].row.fields.push(
      this.state.formTemplate[indexRow].row.fields[0]
    );
    const positionNewField = formTemplate[indexRow].row.fields.length - 1;
    formTemplate[indexRow].row.fields[positionNewField].label = `${
      formTemplate[indexRow].row.fields[positionNewField].label
    } [${positionNewField + 1}]`;
    formTemplate[indexRow].row.fields[positionNewField].name = `${
      formTemplate[indexRow].row.fields[positionNewField].name
    }_${positionNewField + 1}`;
    formTemplate[indexRow].row.fields[positionNewField].indexField = indexRow;
    this.setState({
      formTemplate: formTemplate,
    });
  };

  removeGrouping = (indexRow: number, indexField: number) => {
    const formTemplate = cloneDeep(this.state.formTemplate);
    formTemplate[indexRow].row.fields.splice(indexField, 1);
    this.setState({
      formTemplate: formTemplate,
    });
  };

  addGroupingSelect = (
    indexRow: number,
    indexField: number,
    handleChange?: any
  ) => {
    const formTemplate = cloneDeep(this.state.formTemplate);
    const formState = this.state.formState;
    const fields = formTemplate[indexRow].row.fields;
    const newField = cloneDeep(fields[0]);
    const {
      name,
      label,
      defaultData,
      multiple,
      grouped,
      uniquePerGroup,
    } = newField;
    let defaultValue = multiple ? [] : defaultData;
    newField.defaultData = defaultValue;
    fields.push(newField);
    formState[`${name}_${fields.length}`] = defaultValue;
    formTemplate[indexRow].row.fields = fields.map(
      (field: any, index: number) => {
        if (index) {
          field.name = `${name}_${index + 1}`;
          field.label = `${label} [${index + 1}]`;
          field.indexField = index;
        }
        return cloneDeep(field);
      }
    );
    const fieldValues = formState[`${name}_${fields.length}`];
    const aditionalArguments: any[] = [];
    if (grouped && uniquePerGroup) {
      const allData = fields.reduce((accumulator: any, field: any) => {
        const newData = field.data.filter(
          ({ value: fieldValue }: any) =>
            !accumulator.find(
              ({ value: accValue }: any) => fieldValue === accValue
            )
        );
        return [...accumulator, ...newData];
      }, []);
      aditionalArguments.push({});
      const unusedData = fields.reduce((remaningData: any, field: any) => {
        const fieldData = formState[field.name];
        return remaningData.filter((remainingDataItem: any) => {
          const isValueUsed = fieldData.some(
            (fieldDataItem: any) => remainingDataItem.key === fieldDataItem.key
          );
          return !isValueUsed;
        });
      }, allData);
      fields.forEach((field: any) => {
        field.defaultData = formState[field.name];
        field.data = [...formState[field.name], ...unusedData];
        const groupedValues = aditionalArguments[aditionalArguments.length - 1];
        groupedValues[field.name] = field.defaultData;
      });
      formTemplate[indexRow].row.fields = fields;
    }
    this.setState({
      formTemplate,
      formState,
    });
    const fieldValue = { [name]: fieldValues };
    this.props.onChange(fieldValue, ...aditionalArguments);
    if (handleChange) {
      handleChange(null, null, fieldValue, ...aditionalArguments);
    }
  };

  removeGroupingSelect = (
    indexRow: number,
    indexField: number,
    handleChange?: any
  ) => {
    const formTemplate = cloneDeep(this.state.formTemplate);
    const formState = this.state.formState;
    const fields = formTemplate[indexRow].row.fields;
    const deletedField = formTemplate[indexRow].row.fields[indexField];
    const deletedValues = formState[deletedField.name];
    const { name, label, grouped, uniquePerGroup } = fields[0];
    fields.splice(indexField, 1);
    delete formState[deletedField.name];
    formTemplate[indexRow].row.fields = fields.map(
      (field: any, index: number) => {
        if (index) {
          const value = formState[field.name];
          delete formState[field.name];
          field.name = `${name}_${index + 1}`;
          field.label = `${label} [${index + 1}]`;
          field.indexField = index;
          formState[field.name] = value;
        }
        return field;
      }
    );
    const aditionalArguments: any[] = [];
    if (grouped && uniquePerGroup) {
      const allData = fields.reduce((accumulator: any, field: any) => {
        const newData = field.data.filter(
          ({ value: fieldValue }: any) =>
            !accumulator.find(
              ({ value: accValue }: any) => fieldValue === accValue
            )
        );
        return [...accumulator, ...newData];
      }, deletedValues);
      aditionalArguments.push({});
      const unusedData = fields.reduce((remaningData: any, field: any) => {
        const fieldData = formState[field.name];
        return remaningData.filter((remainingDataItem: any) => {
          const isValueUsed = fieldData.some(
            (fieldDataItem: any) => remainingDataItem.key === fieldDataItem.key
          );
          return !isValueUsed;
        });
      }, allData);
      fields.forEach((field: any) => {
        field.defaultData = formState[field.name];
        field.data = [...formState[field.name], ...unusedData];
        const groupedValues = aditionalArguments[aditionalArguments.length - 1];
        groupedValues[field.name] = field.defaultData;
      });
      formTemplate[indexRow].row.fields = fields;
    }
    this.setState({
      formTemplate,
      formState,
    });
    this.props.onChange(null, ...aditionalArguments);
    if (handleChange) {
      handleChange(null, null, null, ...aditionalArguments);
    }
  };

  addGroupingRow(indexRow: number) {
    let formTemplate = cloneDeep(this.state.formTemplate);
    const indexGrouped = formTemplate.findIndex(
      (item: any) => item.row.grouped
    );
    const sizeGrouped = formTemplate.filter((item: any) => item.row.grouped)
      .length;
    const positionAdd = indexGrouped + sizeGrouped;
    formTemplate.splice(positionAdd, 0, this.state.formTemplate[indexRow]);
    formTemplate[positionAdd].row.groupedCopy = true;
    formTemplate[positionAdd].row.removed = false;
    const randomString = `_${Math.random()
      .toString(36)
      .substring(7)}`;
    formTemplate[positionAdd].row.fields.forEach((item: any, i: number) => {
      item.name = `${item.name}${randomString}`;
    });
    delete formTemplate[positionAdd].row.id;
    this.setState({
      formTemplate: formTemplate,
    });
  }

  removeGroupingRow(indexRow: any) {
    const formTemplate = this.state.formTemplate;
    formTemplate[indexRow].row.removed = true;
    this.setState({
      formTemplate: formTemplate,
    });
  }

  goBackList(indexRow: any) {
    const formTemplate = this.state.formTemplate;
    formTemplate[indexRow].row.removed = false;
    this.setState({
      formTemplate: formTemplate,
    });
  }

  handleAccordion = (e: any, titleProps: any) => {
    this.props.accordionStatusOpened(!titleProps.active);
    this.setState({ activeAccordion: !titleProps.active });
  };

  mountValue(formState: any, itemInput: any) {
    let value: any = null;
    if (formState[itemInput.name] && formState[itemInput.name].length > 0) {
      value = formState[itemInput.name];
    } else if (
      formState[itemInput.name] &&
      formState[itemInput.name].length === 0
    ) {
      value = undefined;
    } else if (itemInput.defaultData.length > 0) {
      value = itemInput.defaultData;
    } else {
      value = undefined;
    }
    return value;
  }

  mountActionGrouping = (
    label: string,
    indexRow: number,
    indexField: number,
    onChange?: any
  ) => {
    const addButton =
      indexField === 0 ? (
        <Popup
          key={`${indexRow}_${indexField}`}
          trigger={
            <Button
              type="button"
              icon="add"
              size="mini"
              floated="right"
              positive
              compact
              style={{ marginBottom: "4px" }}
              onClick={() => this.addGrouping(indexRow, indexField)}
            />
          }
          inverted
          content="Adicionar agrupamento"
        />
      ) : null;

    const removeButton =
      indexField !== 0 ? (
        <Popup
          key={`${indexRow}_${indexField}`}
          trigger={
            <Button
              type="button"
              icon="remove"
              size="mini"
              floated="right"
              negative
              compact
              style={{ marginBottom: "4px" }}
              onClick={() => this.removeGrouping(indexRow, indexField)}
            />
          }
          inverted
          content="Remover agrupamento"
        />
      ) : null;

    return [label, addButton, removeButton];
  };

  mountActionGroupingSelect = (
    label: string,
    indexRow: number,
    indexField: number,
    onChange?: any
  ) => {
    const addButton =
      indexField === 0 ? (
        <Popup
          key={`${indexRow}_${indexField}`}
          trigger={
            <Button
              type="button"
              icon="add"
              size="mini"
              floated="right"
              positive
              compact
              style={{ marginBottom: "4px" }}
              onClick={() =>
                this.addGroupingSelect(indexRow, indexField, onChange)
              }
            />
          }
          inverted
          content="Adicionar agrupamento"
        />
      ) : null;

    const removeButton =
      indexField !== 0 ? (
        <Popup
          key={`${indexRow}_${indexField}`}
          trigger={
            <Button
              type="button"
              icon="remove"
              size="mini"
              floated="right"
              negative
              compact
              style={{ marginBottom: "4px" }}
              onClick={() =>
                this.removeGroupingSelect(indexRow, indexField, onChange)
              }
            />
          }
          inverted
          content="Remover agrupamento"
        />
      ) : null;

    return [label, addButton, removeButton];
  };

  mountActionGroupingRow = (itemRow: any, indexRow: number) => {
    const button = !itemRow.row.groupedCopy ? (
      <Popup
        key={Math.random()
          .toString(36)
          .substring(7)}
        trigger={
          <Button.Group size="mini" floated="right" compact>
            <Button
              type="button"
              icon="add"
              size="mini"
              floated="right"
              positive
              compact
              onClick={() => this.addGroupingRow(indexRow)}
            />
            {!itemRow.row.removed ? (
              <Button
                type="button"
                icon="remove"
                size="mini"
                floated="right"
                negative
                compact
                onClick={() => this.removeGroupingRow(indexRow)}
              />
            ) : (
              <Button
                type="button"
                basic
                color="red"
                icon="add"
                size="mini"
                floated="right"
                compact
                onClick={() => this.goBackList(indexRow)}
              />
            )}
          </Button.Group>
        }
        inverted
        content="Adicionar ou Remover agrupamento"
      />
    ) : itemRow.row.removed ? (
      <Popup
        key={Math.random()
          .toString(36)
          .substring(7)}
        trigger={
          <Button
            type="button"
            basic
            color="red"
            icon="add"
            size="mini"
            floated="right"
            compact
            onClick={() => this.goBackList(indexRow)}
          />
        }
        inverted
        content="Retornar para lista"
      />
    ) : (
      <Popup
        key={Math.random()
          .toString(36)
          .substring(7)}
        trigger={
          <Button
            type="button"
            icon="remove"
            size="mini"
            floated="right"
            negative
            compact
            onClick={() => this.removeGroupingRow(indexRow)}
          />
        }
        inverted
        content="Remover agrupamento"
      />
    );

    return button;
  };

  mountForm(
    itemInput: any,
    indexRow: number,
    indexField: number,
    itemRow: any
  ) {
    switch (itemInput.type) {
      case "submit":
        return (
          <div
            key={`${indexRow}_${indexField}`}
            style={itemInput.inLine ? { position: "relative" } : {}}
          >
            <Form.Input
              data-testid={itemInput.testId}
              fluid
              name={itemInput.name}
              style={
                itemInput.inLine ? { position: "absolute", bottom: "0px" } : {}
              }
              children={
                <Button
                  style={
                    itemInput.floated === "right" ? { marginLeft: "auto" } : {}
                  }
                  width={itemInput.width}
                  icon
                  labelPosition="left"
                  color={itemInput.color}
                  type="submit"
                  disabled={itemInput.disabled}
                >
                  <Icon name={itemInput.icon} />
                  {itemInput.label}
                </Button>
              }
            />
          </div>
        );
        break;
      case "reset":
        return (
          <Form.Input
            data-testid={itemInput.testId}
            key={`${indexRow}_${indexField}`}
            fluid
            name={itemInput.name}
            width={itemInput.width}
            children={
              <Button
                onClick={() => this.resetForm()}
                style={
                  itemInput.floated === "right" ? { marginLeft: "auto" } : {}
                }
                icon
                labelPosition="left"
                color={itemInput.color}
                type="reset"
              >
                <Icon name={itemInput.icon} />
                {itemInput.label}
              </Button>
            }
          />
        );
        break;
      case "button":
        return (
          <Form.Input
            data-testid={itemInput.testId}
            key={`${indexRow}_${indexField}`}
            fluid
            name={itemInput.name}
            children={
              <Button
                width={itemInput.width}
                onClick={itemInput.onClick}
                style={
                  itemInput.floated === "right" ? { marginLeft: "auto" } : {}
                }
                icon
                labelPosition="left"
                color={itemInput.color}
                type="button"
              >
                <Icon name={itemInput.icon} />
                {itemInput.label}
              </Button>
            }
          />
        );
        break;
      case "date":
        return (
          <Form.Input
            data-testid={itemInput.testId}
            key={`${indexRow}_${indexField}`}
            fluid
            type={itemInput.type}
            label={itemInput.label}
            name={itemInput.name}
            placeholder={itemInput.placeholder}
            value={this.state.formState[itemInput.name]}
            maxLength={itemInput.maxLength}
            required={itemInput.required}
            validations={itemInput.validations}
            validationErrors={itemInput.validationErrors}
            errorLabel={errorLabel}
            defaultValue={itemInput.defaultValue}
            width={itemInput.width}
            children={
              <DatePicker
                locale="pt-br"
                selected={
                  this.state.formState[itemInput.name]
                    ? this.state.formState[itemInput.name]
                    : itemInput.defaultValue &&
                      moment(itemInput.defaultValue).toDate()
                }
                placeholderText={itemInput.placeholder}
                dateFormat={itemInput.dateFormat}
                minDate={itemInput.minDate}
                maxDate={itemInput.maxDate}
                onChange={this.handleChangeDateChange.bind(
                  this,
                  itemInput.name
                )}
                disabled={itemInput.disabled}
              />
            }
          />
        );
        break;
      case "dateRange":
        return (
          <Form.Input
            data-testid={itemInput.testId}
            key={`${indexRow}_${indexField}`}
            fluid
            type={itemInput.type}
            label={itemInput.label}
            name={itemInput.name}
            placeholder={itemInput.placeholder}
            value={this.state.formState[itemInput.name]}
            required={itemInput.required}
            validations={itemInput.validations}
            validationErrors={itemInput.validationErrors}
            errorLabel={errorLabel}
            width={itemInput.width}
            children={
              <DatesRangeInput
                localization="pt-br"
                allowSameEndDate
                name={itemInput.name}
                placeholder={itemInput.placeholder}
                value={
                  this.state.formState[itemInput.name]
                    ? this.state.formState[itemInput.name]
                    : ""
                }
                iconPosition="left"
                onChange={this.handleChange}
                minDate={itemInput.minDate}
                maxDate={itemInput.maxDate}
                dateFormat={itemInput.dateFormat}
                popupPosition="bottom right"
                closable
                hideMobileKeyboard
                clearable={true}
                autoComplete="off"
              />
            }
          />
        );
        break;
      case "select":
        let { defaultData } = itemInput;
        if (itemInput.multiple) {
          defaultData = defaultData || [];
          if (defaultData.length) {
            defaultData = defaultData.map((item: any) => item.value);
          }
        }
        return (
          <Form.Select
            data-testid={itemInput.testId}
            key={`${indexRow}_${indexField}`}
            label={
              itemInput.grouped
                ? this.mountActionGroupingSelect(
                    itemInput.label,
                    indexRow,
                    indexField,
                    itemInput.handleChange
                  )
                : itemInput.label
            }
            fluid
            search={itemInput.search}
            name={itemInput.name}
            placeholder={itemInput.placeholder}
            width={itemInput.width}
            disabled={itemInput.disabled}
            value={defaultData}
            required={itemInput.required}
            validations={itemInput.validations}
            validationErrors={itemInput.validationErrors}
            errorLabel={errorLabel}
            options={itemInput.data}
            multiple={itemInput.multiple}
            onChange={this.handleChangeSelect.bind(
              this,
              itemInput.name,
              itemInput.handleChange,
              indexRow,
              indexField
            )}
            onSearchChange={itemInput.handleSearchChange}
          />
        );
        break;
      case "multiSelect":
        {
          return (
            <Form.Input
              data-testid={itemInput.testId}
              key={`${indexRow}_${indexField}`}
              fluid
              type={itemInput.type}
              label={
                itemInput.grouped
                  ? this.mountActionGrouping(
                      itemInput.label,
                      indexRow,
                      indexField
                    )
                  : itemInput.label
              }
              name={itemInput.name}
              placeholder={itemInput.placeholder}
              width={itemInput.width}
              value={
                this.state.formState[itemInput.name]
                  ? this.state.formState[itemInput.name]
                  : itemInput.defaultData
              }
              maxLength={itemInput.maxLength}
              required={itemInput.required}
              validations={itemInput.validations}
              validationErrors={itemInput.validationErrors}
              errorLabel={errorLabel}
              disabled={itemInput.disabled}
              children={
                <Picky
                  id={`${indexRow}_${indexField}`}
                  filterPlaceholder={"Pesquisar"}
                  value={
                    this.state.formState[itemInput.name]
                      ? this.state.formState[itemInput.name]
                      : itemInput.defaultData
                  }
                  onChange={this.handleChangeMultSelect.bind(
                    this,
                    itemInput.name
                  )}
                  valueKey="value"
                  labelKey="text"
                  multiple={itemInput.multiple}
                  // includeSelectAll={
                  //   itemInput.includeSelectAll === false ? false : true
                  // }
                  renderSelectAll={({
                    filtered,
                    allSelected,
                    toggleSelectAll,
                    tabIndex,
                    multiple,
                    disabled,
                  }) => {
                    const checkboxRef = React.createRef<HTMLInputElement>();
                    const includeSelectAll =
                      itemInput.includeSelectAll === false ? false : true;
                    // React.useEffect(() => {
                    //   if (checkboxRef.current === null) return;
                    //   checkboxRef.current.indeterminate =
                    //     allSelected === "partial";
                    // }, [allSelected]);
                    // if (multiple && !filtered && includeSelectAll) {
                    if (multiple && includeSelectAll) {
                      return (
                        <div
                          tabIndex={tabIndex}
                          role="option"
                          data-testid="selectall"
                          id={tabIndex + "-option-" + "selectall"}
                          data-selectall="true"
                          aria-selected={allSelected === "all"}
                          className={
                            allSelected === "all" ? "option selected" : "option"
                          }
                          onClick={toggleSelectAll}
                          onKeyPress={toggleSelectAll}
                        >
                          <input
                            type="checkbox"
                            ref={checkboxRef}
                            readOnly
                            data-testid="selectall-checkbox"
                            tabIndex={-1}
                            checked={allSelected === "all"}
                            aria-label="select all"
                            disabled={disabled}
                          />
                          <span data-testid="select-all-text">
                            {"Selecionar todos"}
                          </span>
                        </div>
                      );
                    } else {
                      return null;
                    }
                  }}
                  selectAllMode={"filtered"}
                  includeFilter={true}
                  dropdownHeight={250}
                  options={itemInput.data ? itemInput.data : []}
                  open={false}
                  selectAllText={"Selecionar todos"}
                  placeholder={itemInput.placeholder}
                  manySelectedPlaceholder={"%s selecionados"}
                  allSelectedPlaceholder={"%s selecionados"}
                  disabled={itemInput.disabled}
                />
              }
            />
          );
        }
        break;
      case "multiSelectArea": {
        return (
          <Form.Input
            key={`${indexRow}_${indexField}`}
            fluid
            type={itemInput.type}
            label={
              itemInput.grouped
                ? this.mountActionGrouping(
                    itemInput.label,
                    indexRow,
                    indexField
                  )
                : itemInput.label
            }
            name={itemInput.name}
            placeholder={itemInput.placeholder}
            width={itemInput.width}
            value={this.mountValue(this.state.formState, itemInput)}
            maxLength={itemInput.maxLength}
            required={itemInput.required}
            validations={itemInput.validations}
            validationErrors={itemInput.validationErrors}
            errorLabel={errorLabel}
            disabled={itemInput.disabled}
            children={
              <div style={{ width: "100%" }}>
                <MultiSelect
                  key={`${indexRow}_${indexField}`}
                  items={itemInput.data}
                  selectedItems={
                    this.state.formState[itemInput.name] &&
                    this.state.formState[itemInput.name].length > 0
                      ? this.state.formState[itemInput.name]
                      : this.state.formState[itemInput.name] &&
                        this.state.formState[itemInput.name].length === 0
                      ? undefined
                      : itemInput.defaultData
                  }
                  onChange={
                    typeof this.props.onChange !== "undefined"
                      ? this.handleChangeMultSelect.bind(this, itemInput.name)
                      : null
                  }
                  responsiveHeight={250}
                  messages={{
                    searchPlaceholder: "Buscar...",
                    noItemsMessage: "Sem itens...",
                    noneSelectedMessage: "Nenhum",
                    selectedMessage: "selecionados",
                    selectAllMessage: "Selecionar todos",
                    clearAllMessage: "Limpar",
                    disabledItemsTooltip: "Você pode selecionar apenas 1 item",
                  }}
                />
              </div>
            }
          />
        );
      }
      case "checkbox":
        return (
          <Checkbox
            data-testid={itemInput.testId}
            className="form-checkbox"
            key={`${indexRow}_${indexField}`}
            name={itemInput.name}
            label={itemInput.label}
            defaultChecked={itemInput.defaultChecked}
            checked={itemInput.defaultChecked}
            required={itemInput.required}
            validations={itemInput.validations}
            validationErrors={itemInput.validationErrors}
            errorLabel={errorLabel}
            disabled={itemInput.disabled}
            toggle={itemInput.toggle}
            onChange={this.handleCheckboxChange.bind(this, itemInput.name)}
          />
        );
        break;
      case "search":
        return (
          <Form.Input
            data-testid={itemInput.testId}
            key={`${indexRow}_${indexField}`}
            fluid
            label={itemInput.label}
            name={itemInput.name}
            maxLength={itemInput.maxLength}
            children={
              <Search
                fluid
                placeholder={itemInput.placeholder}
                loading={itemInput.isLoading}
                noResultsMessage={itemInput.notFound}
                onResultSelect={itemInput.handleResultSelect}
                onSearchChange={itemInput.handleSearchChange}
                results={itemInput.results}
                value={itemInput.value}
              />
            }
          />
        );
        break;
      case "textArea":
        return (
          <Form.TextArea
            data-testid={itemInput.testId}
            key={`${indexRow}_${indexField}`}
            type={itemInput.type}
            label={itemInput.label}
            name={itemInput.name}
            placeholder={itemInput.placeholder}
            width={itemInput.width}
            maxLength={itemInput.maxLength}
            defaultValue={itemInput.defaultValue}
            required={itemInput.required}
            validations={itemInput.validations}
            validationErrors={itemInput.validationErrors}
            errorLabel={errorLabel}
            disabled={itemInput.disabled}
          />
        );
        break;
      case "header":
        return (
          <Header
            key={`${indexRow}_${indexField}`}
            as={itemInput.as}
            color={itemInput.color ? itemInput.color : "black"}
          >
            {itemInput.icon && <Icon name={itemInput.icon} />}
            <Header.Content>{itemInput.label}</Header.Content>
          </Header>
        );
        break;
      case "dropdown":
        return (
          <Form.Input
            data-testid={itemInput.testId}
            key={`${indexRow}_${indexField}`}
            fluid
            type={itemInput.type}
            label={
              itemInput.grouped
                ? this.mountActionGrouping(
                    itemInput.label,
                    indexRow,
                    indexField
                  )
                : itemInput.label
            }
            name={itemInput.name}
            value={this.state.formState[itemInput.name]}
            width={itemInput.width}
            maxLength={itemInput.maxLength}
            required={itemInput.required}
            validations={itemInput.validations}
            validationErrors={itemInput.validationErrors}
            errorLabel={errorLabel}
            children={
              <Dropdown
                fluid={itemInput.fluid || true}
                selection={itemInput.selection || true}
                noResultsMessage={itemInput.noResultsMessage}
                noItemsMessage={itemInput.noItemsMessage}
                multiple={itemInput.multiple}
                search={itemInput.search || true}
                options={itemInput.data || []}
                onChange={this.handleChangeDropdown.bind(this, itemInput.name)}
                placeholder={itemInput.placeholder}
                disabled={itemInput.disabled}
                loading={this.props.loading}
                width={itemInput.width}
                compact={itemInput.compact}
                onSearchChange={itemInput.handleSearchChange}
              />
            }
          />
        );
      case "radio":
        return (
          <div className="field" key={`${indexRow}_${indexField}`}>
            <label>
              {itemInput.label} <span style={{ color: "red" }}>*</span>
            </label>
            <RadioGroup
              data-testid={itemInput.testId}
              width={itemInput.width}
              name={itemInput.name}
              required={itemInput.required}
              errorLabel={errorLabelRadio}
              validationErrors={itemInput.validationErrors}
            >
              {itemInput.data.map((item: any, index: number) =>
                itemInput.variation &&
                (itemInput.variation === INPUT_VARIATIONS.TOGGLE ||
                  itemInput.variation === INPUT_VARIATIONS.SLIDER) ? (
                  <Radio
                    toggle={itemInput.variation === INPUT_VARIATIONS.TOGGLE}
                    slider={itemInput.variation === INPUT_VARIATIONS.SLIDER}
                    key={index}
                    label={item.text}
                    value={item.value}
                    defaultChecked={itemInput.value === item.value}
                    disabled={itemInput.disabled}
                  />
                ) : itemInput.variation &&
                  itemInput.variation === INPUT_VARIATIONS.CHECKBOX ? (
                  <CheckboxSemantic
                    key={index}
                    label={item.text}
                    value={item.value}
                    defaultChecked={itemInput.value === item.value}
                    disabled={itemInput.disabled}
                  />
                ) : (
                  <Radio
                    key={index}
                    label={item.text}
                    value={item.value}
                    defaultChecked={itemInput.value === item.value}
                    disabled={itemInput.disabled}
                  />
                )
              )}
            </RadioGroup>
          </div>
        );
      case "multiprogress":
        const canRenderMultiProgressBar = this.canRenderMultiProgress(
          itemInput.data
        );
        return (
          <Grid.Column
            className="field"
            width={itemInput.width}
            key={`${indexRow}_${indexField}`}
          >
            <MagaMultiProgressBar
              readings={
                canRenderMultiProgressBar ? itemInput.data[0].readings : []
              }
              minWidth={1}
              mainPopup={
                canRenderMultiProgressBar ? itemInput.data[0].mainPopup : {}
              }
            />
          </Grid.Column>
        );
      default:
        return (
          <Form.Input
            data-testid={itemInput.testId}
            className={itemInput.className}
            key={`${indexRow}_${indexField}`}
            fluid
            defaultValue={itemInput.defaultValue}
            placeholder={itemInput.placeholder}
            type={itemInput.type}
            label={itemInput.label}
            name={itemInput.name}
            width={itemInput.width}
            minLength={itemInput.minLength}
            maxLength={itemInput.maxLength}
            required={itemInput.required}
            validations={itemInput.validations}
            validationErrors={itemInput.validationErrors}
            errorLabel={errorLabel}
            value={this.state.formState[itemInput.name]}
            disabled={itemInput.disabled}
            min={itemInput.min}
            max={itemInput.max}
            onChange={
              itemInput.onChange ||
              this.handleChangeInput.bind(this, itemInput.name)
            }
            onBlur={this.handleBlurInput}
            children={
              itemInput.mask && (
                <ReactInputMask
                  value={
                    this.state.formState[itemInput.name] ||
                    itemInput.defaultValue
                  }
                  name={itemInput.name}
                  placeholder={itemInput.placeholder}
                  validations={itemInput.validations}
                  mask={itemInput.mask}
                  maskChar={itemInput.maskChar}
                  formatChars={itemInput.formatChars}
                  alwaysShowMask={itemInput.alwaysShowMask}
                  // onChange={this.handleChangeInputMask.bind(this, itemInput)}
                  onChange={this.handleChangeInputMask}
                  onBlur={this.handleBlurInput}
                />
              )
            }
          />
        );
        break;
    }
  }

  canRenderMultiProgress = (data: any) =>
    data && data.length && data[0].readings && Array.isArray(data[0].readings);

  render() {
    const {
      title,
      border,
      loading,
      refForm,
      accordion,
      actionRightTop,
    } = this.props;
    const { formTemplate, activeAccordion } = this.state;
    const defineBorder = border
      ? border === "attached"
        ? "attached segment"
        : "segment"
      : null;

    return (
      <Accordion>
        <Segment color="blue" loading={loading}>
          {actionRightTop && actionRightTop}
          {accordion && (
            <Accordion.Title
              active={activeAccordion}
              index={0}
              onClick={this.handleAccordion}
            >
              <Label color="blue" size="large" ribbon>
                <Icon name="dropdown" />
                {title}
              </Label>
            </Accordion.Title>
          )}
          <Accordion.Content active={activeAccordion}>
            <>
              {accordion && <Divider />}
              <Form
                id={refForm}
                className={defineBorder}
                ref={(ref: any) => (this.form = ref)}
                onValidSubmit={this.onValidSubmit}
              >
                {formTemplate.map((itemRow: any, indexRow: number) => (
                  <Form.Group
                    key={indexRow}
                    style={
                      itemRow.row.removed
                        ? {
                            backgroundColor: "#ffebee",
                            paddingTop: "10px",
                            paddingBottom: "10px",
                            borderRadius: "5px",
                          }
                        : {
                            flexWrap: "wrap",
                          }
                    }
                  >
                    {itemRow.row.grouped &&
                      this.mountActionGroupingRow(itemRow, indexRow)}
                    {itemRow.row.fields.map(
                      (itemInput: any, indexField: number) =>
                        this.mountForm(itemInput, indexRow, indexField, itemRow)
                    )}
                    {itemRow.row.removed && (
                      <div>
                        <Label color="red" size="tiny">
                          Agrupamento será removido ao salvar
                        </Label>
                      </div>
                    )}
                  </Form.Group>
                ))}
              </Form>
              {this.props.children}
            </>
          </Accordion.Content>
        </Segment>
      </Accordion>
    );
  }
}
