"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

var _react = _interopRequireDefault(require("react"));

var _reactDom = _interopRequireDefault(require("react-dom"));

var _fbemitter = require("fbemitter");

var _formValidator = _interopRequireDefault(require("./form-validator"));

var _formElements = _interopRequireDefault(require("./form-elements"));

var _multiColumn = require("./multi-column");

var _customElement = _interopRequireDefault(require("./form-elements/custom-element"));

var _LoaderButton = _interopRequireDefault(require("./components/LoaderButton"));

var _registry = _interopRequireDefault(require("./stores/registry"));

var _store = _interopRequireDefault(require("./stores/store"));

var _Notifier = _interopRequireDefault(require("./components/Notifier"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

const {
  Image,
  Checkboxes,
  Signature,
  Download,
  Camera,
  FileUpload
} = _formElements.default;

class ReactForm extends _react.default.Component {
  constructor(props) {
    super(props);

    _defineProperty(this, "form", void 0);

    _defineProperty(this, "inputs", {});

    _defineProperty(this, "answerData", void 0);

    this.answerData = this._convert(props.answer_data);
    this.emitter = new _fbemitter.EventEmitter();
    this.getDataById = this.getDataById.bind(this);
    this.state = {
      isLoading: false
    };
  }

  componentDidMount() {
    _store.default.dispatch("saveRootURL", this.props.rootURL);

    _store.default.dispatch("saveUser", this.props.user_id);

    _store.default.dispatch("saveTranslate", this.props.translate);
  }

  _convert(answers) {
    if (Array.isArray(answers)) {
      const result = {};
      answers.forEach(x => {
        if (x.name && x.name.indexOf("tags_") > -1) {
          result[x.name] = x.value.map(y => y.value);
        } else {
          result[x.name] = x.value;
        }
      });
      return result;
    }

    return answers || {};
  }

  _getDefaultValue(item) {
    return this.answerData[item.field_name];
  }

  _optionsDefaultValue(item) {
    const defaultValue = this._getDefaultValue(item);

    if (defaultValue) {
      return defaultValue;
    }

    const defaultChecked = [];
    item.options.forEach(option => {
      if (this.answerData[`option_${option.key}`]) {
        defaultChecked.push(option.key);
      }
    });
    return defaultChecked;
  }

  _getItemValue(item, ref) {
    let $item = {
      element: item.element,
      value: ""
    };

    if (item.element === "Rating") {
      $item.value = ref.inputField.current.state.rating;
    } else if (item.element === "Tags") {
      $item.value = ref.inputField.current.state.value;
    } else if (item.element === "DatePicker") {
      $item.value = ref.state.value;
    } else if (item.element === "Camera") {
      $item.value = ref.state.img ? ref.state.img.replace("data:image/png;base64,", "") : "";
    } else if (item.element === 'Signature') {
      $item.value = ref.inputField.current || "";
    } else if (ref && ref.inputField && ref.inputField.current) {
      $item = _reactDom.default.findDOMNode(ref.inputField.current);

      if ($item && typeof $item.value === "string") {
        $item.value = $item.value.trim();
      }
    }

    return $item;
  }

  _isIncorrect(item) {
    let incorrect = false;

    if (item.canHaveAnswer) {
      const ref = this.inputs[item.field_name];

      if (item.element === "Checkboxes" || item.element === "RadioButtons") {
        item.options.forEach(option => {
          const $option = _reactDom.default.findDOMNode(ref.options[`child_ref_${option.key}`]);

          if (option.hasOwnProperty("correct") && !$option.checked || !option.hasOwnProperty("correct") && $option.checked) {
            incorrect = true;
          }
        });
      } else {
        const $item = this._getItemValue(item, ref);

        if (item.element === "Rating") {
          if ($item.value.toString() !== item.correct) {
            incorrect = true;
          }
        } else if ($item.value.toLowerCase() !== item.correct.trim().toLowerCase()) {
          incorrect = true;
        }
      }
    }

    return incorrect;
  }

  _isInvalid(item) {
    let invalid = false;

    if (item.required === true) {
      const ref = this.inputs[item.field_name];

      if (item.element === "Checkboxes" || item.element === "RadioButtons") {
        let checked_options = 0;
        item.options.forEach(option => {
          const $option = _reactDom.default.findDOMNode(ref.options[`child_ref_${option.key}`]);

          if ($option.checked) {
            checked_options += 1;
          }
        });

        if (checked_options < 1) {
          // errors.push(item.label + ' is required!');
          invalid = true;
        }
      } else {
        const $item = this._getItemValue(item, ref);

        if (item.element === "Rating") {
          if ($item.value === 0) {
            invalid = true;
          }
        } else if ($item.value === undefined || $item.value.length < 1 || $item.value === "nothingSelected" // For Dropdown
        ) {
            invalid = true;
          }
      }
    }

    return invalid;
  }

  _collect(item) {
    const itemData = {
      name: item.field_name
    };
    const ref = this.inputs[item.field_name];

    if (item.element === "Checkboxes" || item.element === "RadioButtons") {
      const checked_options = [];
      item.options.forEach(option => {
        const $option = _reactDom.default.findDOMNode(ref.options[`child_ref_${option.key}`]);

        if ($option.checked) {
          checked_options.push(option.key);
        }
      });
      itemData.value = checked_options;
    } else {
      if (!ref) return null;
      itemData.value = this._getItemValue(item, ref).value;
    }

    return itemData;
  }

  _collectFormData(data) {
    const formData = [];
    data.forEach(item => {
      const item_data = this._collect(item);

      if (item_data) {
        formData.push(item_data);
      }
    });
    return formData;
  }

  _getSignatureImg(item) {
    const ref = this.inputs[item.field_name];
    const $canvas_sig = ref.inputField.current;
  }

  handleSubmit(e) {
    try {
      e.preventDefault();
      this.setState({
        isLoading: true
      });
      let errors = [];

      if (!this.props.skip_validations) {
        errors = this.validateForm(); // Publish errors, if any.

        this.emitter.emit("formValidation", errors);
        this.setState({
          isLoading: false
        });
      } // Only submit if there are no errors.


      if (!errors || errors.length < 1) {
        const {
          onSubmit
        } = this.props;

        if (onSubmit) {
          const data = this._collectFormData(this.props.data);

          onSubmit(data).then(() => {
            this.setState({
              isLoading: false
            });
          }).catch(() => {
            this.setState({
              isLoading: false
            });
          });
          this.setState({
            isLoading: false
          });
        } else {
          const $form = _reactDom.default.findDOMNode(this.form);

          $form.submit();
          this.setState({
            isLoading: false
          });
        }
      }

      this.setState({
        isLoading: false
      });
    } catch (error) {
      console.log(error);
      this.setState({
        isLoading: false
      });
    }
  }

  validateEmailAddress(emailString) {
    // check for @ sign
    var atSymbol = emailString.indexOf("@");
    if (atSymbol < 1) return false;
    var dot = emailString.indexOf(".");
    if (dot <= atSymbol + 2) return false; // check that the dot is not at the end

    if (dot === emailString.length - 1) return false;
    return true;
  }

  validateForm() {
    const errors = [];
    let data_items = this.props.data;

    if (this.props.display_short) {
      data_items = this.props.data.filter(i => i.alternateForm === true);
    }

    data_items.forEach(item => {
      if (item.element === "Signature") {
        this._getSignatureImg(item);
      }

      if (this._isInvalid(item)) {
        errors.push(`${item.label} is required!`);
      }

      if (this.props.validateForCorrectness && this._isIncorrect(item)) {
        errors.push(`${item.label} was answered incorrectly!`);
      }

      if (item.element === "TextInput") {
        const $item = this._getItemValue(item, this.inputs[item.field_name]);

        if ($item && $item.value) {
          // Check Pattern
          if (!!item.inputPattern) {
            const reg = new RegExp(item.inputPattern);

            if (!reg.test(String($item.value).toLowerCase().trim())) {
              errors.push(`${item.label} is invalid!`);
            }
          }
        } // Check Email


        if ($item.value && item.isEmail) {
          if (!this.validateEmailAddress($item.value.trim())) {
            errors.push(`${item.label} is invalid`);
          }
        }
      }

      if (item.element === "NumberInput" || item.element === "TextArea") {
        const $item = this._getItemValue(item, this.inputs[item.field_name]); // Check Min


        if (!!item.inputMin) {
          if (Number($item.value) < Number(item.inputMin)) {
            errors.push(`${item.label} must be greater than ${item.inputMin}`);
          }
        } // Check Max


        if (!!item.inputMax) {
          if (Number($item.value) > Number(item.inputMax)) {
            errors.push(`${item.label} must be less than ${item.inputMax}`);
          }
        } // Check Phone number


        if ($item.value && item.isMobile) {
          const mobileRegex = new RegExp("^([0|+[0-9]{1,5})?([7-9][0-9]{9})");

          if (!mobileRegex.test($item.value)) {
            errors.push(`${item.label} is invalid`);
          }
        }
      }
    });
    return errors;
  }

  getDataById(id) {
    const {
      data
    } = this.props;
    return data.find(x => x.id === id);
  }

  getInputElement(item) {
    if (item.custom) {
      return this.getCustomElement(item);
    }

    const inputVal = this._getDefaultValue(item);

    let Input = _formElements.default[item.element];

    if (inputVal && typeof inputVal !== "number" && (inputVal.toString().indexOf("http://") == 0 || inputVal.toString().indexOf("https://") == 0 || inputVal.toString().indexOf("www.") == 0)) {
      Input = _formElements.default["HyperLink"];
    }

    return /*#__PURE__*/_react.default.createElement(Input, {
      handleChange: this.handleChange,
      ref: c => this.inputs[item.field_name] = c,
      mutable: true,
      key: `form_${item.id}`,
      data: item,
      read_only: this.props.read_only,
      defaultValue: this._getDefaultValue(item)
    });
  }

  getContainerElement(item, Element) {
    const controls = item.childItems.map(x => x ? this.getInputElement(this.getDataById(x)) : /*#__PURE__*/_react.default.createElement("div", null, "\xA0"));
    return /*#__PURE__*/_react.default.createElement(Element, {
      mutable: true,
      key: `form_${item.id}`,
      data: item,
      controls: controls
    });
  }

  getSimpleElement(item) {
    const Element = _formElements.default[item.element];
    return /*#__PURE__*/_react.default.createElement(Element, {
      mutable: true,
      key: `form_${item.id}`,
      data: item,
      rootURL: this.props.rootURL
    });
  }

  getCustomElement(item) {
    if (!item.component || typeof item.component !== "function") {
      item.component = _registry.default.get(item.key);

      if (!item.component) {
        console.error(`${item.element} was not registered`);
      }
    }

    const inputProps = item.forwardRef && {
      handleChange: this.handleChange,
      defaultValue: this._getDefaultValue(item),
      ref: c => this.inputs[item.field_name] = c
    };
    return /*#__PURE__*/_react.default.createElement(_customElement.default, _extends({
      mutable: true,
      read_only: this.props.read_only,
      key: `form_${item.id}`,
      data: item
    }, inputProps));
  }

  render() {
    let data_items = this.props.data;

    if (this.props.display_short) {
      data_items = this.props.data.filter(i => i.alternateForm === true);
    }

    data_items.forEach(item => {
      if (item && item.readOnly && item.variableKey && this.props.variables[item.variableKey]) {
        this.answerData[item.field_name] = this.props.variables[item.variableKey];
      }
    });
    const items = data_items.filter(x => !x.parentId).map(item => {
      if (!item) return null;

      switch (item.element) {
        case "TextInput":
        case "NumberInput":
        case "TextArea":
        case "Dropdown":
        case "DatePicker":
        case "RadioButtons":
        case "Rating":
        case "Tags":
        case "Range":
          return this.getInputElement(item);

        case "CustomElement":
          return this.getCustomElement(item);

        case "FourColumnRow":
          return this.getContainerElement(item, _multiColumn.FourColumnRow);

        case "ThreeColumnRow":
          return this.getContainerElement(item, _multiColumn.ThreeColumnRow);

        case "TwoColumnRow":
          return this.getContainerElement(item, _multiColumn.TwoColumnRow);

        case "Signature":
          return /*#__PURE__*/_react.default.createElement(Signature, {
            ref: c => this.inputs[item.field_name] = c,
            read_only: this.props.read_only || item.readOnly,
            mutable: true,
            key: `form_${item.id}`,
            data: item,
            defaultValue: this._getDefaultValue(item)
          });

        case "FileUpload":
          return /*#__PURE__*/_react.default.createElement(FileUpload, {
            ref: c => this.inputs[item.field_name] = c,
            read_only: this.props.read_only || item.readOnly,
            mutable: true,
            key: `form_${item.id}`,
            data: item,
            defaultValue: this._getDefaultValue(item)
          });

        case "Checkboxes":
          return /*#__PURE__*/_react.default.createElement(Checkboxes, {
            ref: c => this.inputs[item.field_name] = c,
            read_only: this.props.read_only,
            handleChange: this.handleChange,
            mutable: true,
            key: `form_${item.id}`,
            data: item,
            defaultValue: this._optionsDefaultValue(item)
          });

        case "Image":
          return /*#__PURE__*/_react.default.createElement(Image, {
            ref: c => this.inputs[item.field_name] = c,
            handleChange: this.handleChange,
            mutable: true,
            key: `form_${item.id}`,
            data: item,
            defaultValue: this._getDefaultValue(item)
          });

        case "Download":
          return /*#__PURE__*/_react.default.createElement(Download, {
            download_path: this.props.download_path,
            mutable: true,
            key: `form_${item.id}`,
            data: item
          });

        case "Camera":
          return /*#__PURE__*/_react.default.createElement(Camera, {
            ref: c => this.inputs[item.field_name] = c,
            read_only: this.props.read_only || item.readOnly,
            mutable: true,
            key: `form_${item.id}`,
            data: item,
            defaultValue: this._getDefaultValue(item)
          });

        default:
          return this.getSimpleElement(item);
      }
    });
    const formTokenStyle = {
      display: "none"
    };
    return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_formValidator.default, {
      emitter: this.emitter
    }), /*#__PURE__*/_react.default.createElement("div", {
      className: "react-form-builder-form"
    }, /*#__PURE__*/_react.default.createElement("form", {
      encType: "multipart/form-data",
      ref: c => this.form = c,
      action: this.props.form_action,
      onSubmit: this.handleSubmit.bind(this),
      method: this.props.form_method
    }, this.props.authenticity_token && /*#__PURE__*/_react.default.createElement("div", {
      style: formTokenStyle
    }, /*#__PURE__*/_react.default.createElement("input", {
      name: "utf8",
      type: "hidden",
      value: "\u2713"
    }), /*#__PURE__*/_react.default.createElement("input", {
      name: "authenticity_token",
      type: "hidden",
      value: this.props.authenticity_token
    }), /*#__PURE__*/_react.default.createElement("input", {
      name: "task_id",
      type: "hidden",
      value: this.props.task_id
    })), items, this.props.show_btns && /*#__PURE__*/_react.default.createElement("div", {
      className: "btn-toolbar action-btns-center"
    }, /*#__PURE__*/_react.default.createElement("input", {
      type: "button",
      onClick: this.props._goback,
      className: "btn mr-2 btn-primary large-btn",
      value: this.props.translate.formBuilder.back
    }), this.props.loaderButton ? /*#__PURE__*/_react.default.createElement(_LoaderButton.default, {
      type: "submit",
      isLoading: this.props.isLoading,
      cssClass: "btn btn-primary large-btn",
      text: this.props.translate.formBuilder.submit
    }) : /*#__PURE__*/_react.default.createElement("button", {
      type: "submit",
      className: "btn btn-primary large-btn"
    }, this.props.translate.formBuilder.submitBtnTxt) // <input
    //   type="submit"
    //   className="btn btn-primary large-btn"
    //   value={this.props.translate.formBuilder.submitBtnTxt}
    // />
    ))), /*#__PURE__*/_react.default.createElement(_Notifier.default, null));
  }

}

exports.default = ReactForm;
ReactForm.defaultProps = {
  validateForCorrectness: false
};