<h3>{{ customTitle ? customTitle : (formMode ? labels2.Title : labels.Title) }}</h3>
<div v-if="!formMode" :id="editor_container" class="WorkflowDesignerJsonEditor"></div>
<el-form
  v-if="formMode"
  ref="form"
  :model="FormData"
  class="WorkflowDesignerWindowForm"
  label-position="top"
  label-width="150px">
  <template v-for="field in fields.filter(field => field.Type !== 'Error')" :key="field.Name">
    <el-form-item :label="getLocalizationParameterLabel(field)" :prop="field.Name" :rules="getFieldRules(field)">
      <el-input v-if="field.Type == 'Text'" v-model="FormData[field.Name]" :readonly="readonly"></el-input>
      <el-input-number v-if="field.Type == 'Number'" v-model="FormData[field.Name]" :disabled="readonly"
                       controls-position="right"></el-input-number>
      <el-checkbox v-if="field.Type == 'Checkbox'" v-model="FormData[field.Name]" :disabled="readonly"></el-checkbox>
      <el-input v-if="field.Type == 'TextArea'" v-model="FormData[field.Name]" :readonly="readonly" :rows="6" type="textarea"></el-input>
      <el-date-picker
        v-if="field.Type == 'DateTime'"
        v-model="FormData[field.Name]"
        value-format="YYYY-MM-DDTHH:mm:ss"
        :class="validateFieldDD(FormData[field.Name]) ? 'WorkflowDesignerInputError' : ''"
        :readonly="readonly"
        type="datetime">
      </el-date-picker>
      <el-date-picker
        v-if="field.Type == 'Date'"
        v-model="FormData[field.Name]"
        :readonly="readonly"
        format="YYYY-MM-DD"
        type="date"
        value-format="YYYY-MM-DD">
      </el-date-picker>
      <el-time-picker
        v-if="field.Type == 'Time'"
        v-model="FormData[field.Name]"
        :picker-options="{
                    selectableRange: '00:00:00 - 23:59:59'
                }"
        :readonly="readonly"
        value-format="HH:mm:ss">
      </el-time-picker>
      <el-select v-if="field.Type == 'Dropdown'" v-model="FormData[field.Name]" :disabled="readonly" placeholder="">
        <el-option
          v-for="item in field.DropdownValues"
          :key="item.Value"
          :label="item.Name"
          :value="item.Value">
        </el-option>
      </el-select>
      <el-select v-if="field.Type == 'MultiSelect'" v-model="FormData[field.Name]" :disabled="readonly" multiple placeholder="">
        <el-option
          v-for="item in field.DropdownValues"
          :key="item.Value"
          :label="item.Name"
          :value="item.Value">
        </el-option>
      </el-select>
      <el-input v-if="field.Type == 'Json'" v-model="FormData[field.Name]" :readonly="readonly"></el-input>
      <el-button v-if="field.Type == 'Json'" :class="'WorkflowDesignerTableCodeActionsButton ' + (editItem == field ? 'is-active' : '')"
                 @click="showjson('DefaultValue', field)"></el-button>
    </el-form-item>
  </template>
  <div style="display: flex;flex-direction: column;gap: 10px">
    <el-alert
      v-for="field in fields.filter(field => field.Type == 'Error')"
      :title="field.Title"
      :description="FormData[field.Name]"
      type="error"
      show-icon
    />
  </div>
</el-form>

<div class="WorkflowDesignerButtons">
  <el-button v-if="!readonly && !formMode" @click="onFormat">{{ labels.Format }}</el-button>
  <el-button v-if="fields" @click="onChangeFormMode">{{ formMode ? labels2.SwitchToJson : labels2.SwitchToConstructor
    }}
  </el-button>
  <el-button v-if="!readonly" type="primary" @click="onSave">{{ ButtonTextSave }}</el-button>
  <el-button @click="onClose">{{ ButtonTextCancel }}</el-button>
</div>
<script type="application/javascript">
  function jsonform_Data(me) {
    return {
      editor_container: me.id + '_editor',
      customTitle: undefined,
      readonly: false,
      editItem: undefined,
      actionType: undefined,
      FormData: {},
      fields: null,
      formMode: false
    }
  }

  function jsonform_Init(me) {
    const {VueConfig} = me;
    const {state: data, methods} = VueConfig

    methods.UpdateLanguage = function () {
      Object.assign(data, {
        labels: WorkflowDesignerConstants.EditJSONLabel,
        labels2: WorkflowDesignerConstants.EditParametersFormlabel,
        ButtonTextSave: WorkflowDesignerConstants.ButtonTextSave,
        ButtonTextCancel: WorkflowDesignerConstants.ButtonTextCancel,
      });
    }

    methods.UpdateLanguage();

    me.failsCount = 0;

    methods.onUpdate = function (value) {
      data.readonly = me.graph.Settings.readonly;

      if (me.options && me.options.customTitle) {
        data.customTitle = me.options.customTitle;
      }
      var fields = undefined;
      var parameterDefinition = me.options.parameterDefinition;
      if (parameterDefinition && parameterDefinition.name) {
        data.actionType = parameterDefinition.name;
        if (Array.isArray(parameterDefinition.type)) {
          for (var i = 0; i < parameterDefinition.type.length; i++) {
            fields = me.graph.getActionParameterDefinition(parameterDefinition.name, parameterDefinition.type[i]);
            if (fields && fields.length > 0)
              break;
          }
        } else {
          fields = me.graph.getActionParameterDefinition(parameterDefinition.name, parameterDefinition.type);
        }
      } else if (Array.isArray(me.options.parameterDefinition)) {
        fields = me.options.parameterDefinition;
        data.actionType = WorkflowDesignerCommon.toJSON(value)['__customtype'];
      }

      if (fields && fields.length > 0) {

        data.formMode = true;
        data.fields = fields;

        if (data.fields.length > 1 && data.fields.filter(function (f) {
          return f.Name === '';
        })[0]) {
          console.error(WorkflowDesignerConstants.EditParametersFormlabel.IncorrectForm);
          methods.showConfirm({
            title: WorkflowDesignerConstants.AlertTitle,
            message: WorkflowDesignerConstants.EditParametersFormlabel.IncorrectForm,
            isAlert: true
          });

          return;
        }

        if (!value && !data.readonly) {
          var tmp = {};

          if (data.fields.length === 1 && data.fields[0].Name === '') {
            if (typeof (data.fields[0].DefaultValue) != 'undefined') {
              if (data.fields[0].Type === 'Checkbox') {
                value = data.fields[0].DefaultValue !== null && data.fields[0].DefaultValue !== undefined && data.fields[0].DefaultValue.toString() === 'true';
              } else if (data.fields[0].Type === 'MultiSelect' && typeof (data.fields[0].DefaultValue) === 'object') {
                value = WorkflowDesignerCommon.toString(data.fields[0].DefaultValue);
              } else if (data.fields[0].Type === 'Json' && typeof (data.fields[0].DefaultValue) === 'object') {
                value = WorkflowDesignerCommon.toString(data.fields[0].DefaultValue);
              } else {
                value = data.fields[0].DefaultValue;
              }
            } else {
              if (data.fields[0].Type === 'Checkbox') {
                value = false;
              } else if (data.fields[0].Type === 'Multiselect') {
                value = [];
              } else {
                value = null;
              }
            }
          } else {
            fields.forEach(function (field) {
              if (field.Type === 'Checkbox') {
                field.DefaultValue = field.DefaultValue !== null && field.DefaultValue !== undefined && field.DefaultValue.toString() === 'true';
              }

              if (typeof (field.DefaultValue) != 'undefined') {
                if (field.Type === 'Json' && typeof (field.DefaultValue) === 'string') {
                  tmp[field.Name] = WorkflowDesignerCommon.toJSON(field.DefaultValue);
                } else if (field.Type === 'MultiSelect') {
                  if (typeof (field.DefaultValue) === 'string') {
                    tmp[field.Name] = WorkflowDesignerCommon.toJSON(field.DefaultValue);
                  } else {
                    try {
                      tmp[field.Name] = [];
                      for (let key in field.DefaultValue) {
                        tmp[field.Name].push(field.DefaultValue[key]);
                      }
                    } catch (e) {
                    }
                  }
                } else {
                  tmp[field.Name] = field.DefaultValue;
                }
              } else {
                tmp[field.Name] = null;
              }
            });
            value = WorkflowDesignerCommon.toString(tmp);
          }
        }
      }

      if (data.formMode) {

        if (value) {
          var serialized = WorkflowDesignerCommon.toJSON(value);

          if (data.fields) {
            data.fields.forEach(function (field) {
              if (field.Type === 'Json') {
                serialized[field.Name] = WorkflowDesignerCommon.toJSON(serialized[field.Name]);
              }
            });
          }

          value = WorkflowDesignerCommon.toString(serialized);
        }

        if (data.fields.length === 1 && data.fields[0].Name === '') {
          if (data.fields[0].Type === 'Text'
            || data.fields[0].Type === 'TextArea'
            || data.fields[0].Type === 'Dropdown'
            || data.fields[0].Type === 'DateTime'
            || data.fields[0].Type === 'Date'
            || data.fields[0].Type === 'Time'
          ) {
            data.FormData = WorkflowDesignerCommon.toJSON('{ "":"' + (value === null ? '' : value) + '"}');
          } else if (data.fields[0].Type === 'Json'
            || data.fields[0].Type === 'Checkbox'
            || data.fields[0].Type === 'MultiSelect'
            || data.fields[0].Type === 'Number'
          ) {
            data.FormData = WorkflowDesignerCommon.toJSON('{ "":' + value + '}');
          } else {
            data.FormData = WorkflowDesignerCommon.toJSON(value);
          }
        } else {
          var formData = WorkflowDesignerCommon.toJSON(value);
          data.fields.forEach(function (field) {
            if (field.Type === 'MultiSelect' && formData[field.Name] !== undefined && typeof (formData[field.Name]) === 'string') {
              var list = WorkflowDesignerCommon.toJSON(formData[field.Name]);
              data.FormData[field.Name] = [];
              list.forEach(function (value) {
                data.FormData[field.Name].push(value);
              });
            } else {
              data.FormData[field.Name] = formData[field.Name];
            }
          });
        }

        if (!data.FormData)
          data.FormData = {};

        for (const key in data.FormData) {
          if (data.FormData.hasOwnProperty(key)) {
            if (key !== '__customtype') {
              var found = false;

              for (var j = 0; j < data.fields.length; j++) {
                if (data.fields[j] && data.fields[j].Name === key) {
                  found = true;
                  break;
                }

              }

              if (!found) {
                delete data.FormData[key];
              }
            }
          }
        }
        data.fields.forEach(function (field) {
          if (data.FormData[field.Name] === undefined) {
            if (field.Type === 'Checkbox') {
              field.DefaultValue = field.DefaultValue !== null && field.DefaultValue !== undefined && field.DefaultValue.toString() === 'true';
            }

            if (typeof (field.DefaultValue) != 'undefined') {
              data.FormData[field.Name] = field.DefaultValue;
            } else {
              data.FormData[field.Name] = null;
            }
          } else {
            if (field.Type === 'Json') {
              data.FormData[field.Name] = typeof data.FormData[field.Name] !== 'undefined'
                ? WorkflowDesignerCommon.toCompactJSON(WorkflowDesignerCommon.toString(data.FormData[field.Name]))
                : null;
            } else if (field.Type === 'Dropdown' && data.FormData[field.Name] !== null && typeof (data.FormData[field.Name]) !== 'string') {
              data.FormData[field.Name] = WorkflowDesignerCommon.toString(data.FormData[field.Name]);
            } else if (field.Type === 'Checkbox' && typeof (data.FormData[field.Name]) !== 'boolean') {
              data.FormData[field.Name] = WorkflowDesignerCommon.toJSON(data.FormData[field.Name]);
            } else if (field.Type === 'Number' && typeof (data.FormData[field.Name]) !== 'number') {
              data.FormData[field.Name] = Number(data.FormData[field.Name]) || null;
            }
          }
        });


        // setTimeout(function(){
        //     methods.renderJSONFields();
        // }, 1);
      } else {
        // TODO wtf
        setTimeout(function () {
          methods.renderEditor(value);
        }, 1);
      }
    };

    methods.getLocalizationParameterLabel = function (field) {
      if (data.labels2.CustomForms[data.actionType] != undefined &&
        data.labels2.CustomForms[data.actionType][field.Name] != undefined) {
        return data.labels2.CustomForms[data.actionType][field.Name];
      }

      var label = field.Title ? field.Title : field.Name;
      if (field.Comment && field.Comment !== '') {
        label = label + ' (' + field.Comment + ')';
      }
      return label;
    };

    methods.getFieldRules = function (field) {
      var rules = [{required: false}];
      if (field.IsRequired) {
        if (field.Type === 'MultiSelect') {
          var validator = function (rule, value, callback) {
            if (data.FormData[field.Name].length > 0) {
              callback();
            } else {
              callback(new Error(rule.message));
            }
          };
          rules.push({validator, message: WorkflowDesignerConstants.FieldIsRequired, trigger: 'change'});
        } else {
          return me.requiredRule();
        }
      }

      return rules;
    };

    methods.showjson = function (name, field) {
      data.editItem = field;
      me.editItem = field;
      var onSuccess = function (value) {
        if (me.editItem) {
          data.FormData[field.Name] = value;
          data.editItem = undefined;
          delete me.editItem;
        }
      };

      var onClose = function (value) {
        data.editItem = undefined;
      };

      var params = {};
      data.jsonform = me.showjson(data.FormData[field.Name], params, onSuccess, onClose);
    };

    methods.renderEditor = function (value) {
      try {
        if (!me.editor) {
          me.editor = ace.edit(data.editor_container);
          var session = me.editor.getSession();
          session.setMode('ace/mode/json5');
          session.setOption('useWorker', false);
        }

        me.editor.setOptions({readOnly: me.graph.Settings.readonly});

        var formattedValue = value ? WorkflowDesignerCommon.toPrettyJSON(value) : '';
        me.editor.setValue(formattedValue ? formattedValue : '');
        me.editor.clearSelection();
        me.failsCount = 0;
      } catch (err) {
        me.failsCount += 1;
        if (me.failsCount > 10) {
          return;
        }
        setTimeout(function () {
          methods.renderEditor(value);
        }, 1);
      }
    };

    methods.validateFieldDD = function (value) {
      if (name === 'DateTime' && value && !moment(value, moment.ISO_8601).isValid())
        return WorkflowDesignerConstants.EditParametersFormlabel.DateShouldBeInISOFormat;
    };

    methods.renderJSONFields = function () {
      data.fields.forEach(function (field) {
        if (field.Type === 'Json') {
          if (!me.editors) me.editors = {};

          var editor = me.editors[field.Name];
          if (!editor) {
            editor = me.editors[field.Name] = ace.edit(field.Name + '_editor');
            var session = editor.getSession();
            session.setMode('ace/mode/json5');
            session.setOption('useWorker', false);
          }

          editor.setOptions({readOnly: me.graph.Settings.readonly});
          var value = data.FormData[field.Name];

          if (typeof value === 'object') {
            var formattedValue = WorkflowDesignerCommon.toString(value);
            editor.setValue(formattedValue ? formattedValue : '');
          } else {
            var formattedValue = WorkflowDesignerCommon.toPrettyJSON(value);
            editor.setValue(formattedValue ? formattedValue : '');
          }

          editor.clearSelection();
        }
      });
    }

    methods.extractFormData = function () {
      var formData = WorkflowDesignerCommon.clone(data.FormData);

      data.fields.forEach(function (field) {
        if (field.Type === 'Json') {
          if (me.editors && me.editors[field.Name]) {
            var value = me.editors[field.Name].getValue();
            formData[field.Name] = value;
          } else {
            formData[field.Name] = formData[field.Name] === '' ? undefined : formData[field.Name];
          }
        }

        if (field.Type === 'MultiSelect') {
          formData[field.Name] = WorkflowDesignerCommon.toString(formData[field.Name]);
        }
      });

      return formData;
    }

    methods.onChangeFormMode = function () {
      data.formMode = !data.formMode;

      if (data.formMode) {
        // TODO editor is not rendered
        var value = me?.editor?.getValue();
        if (data.fields.length === 1 && data.fields[0].Name === '') {
          if (data.fields[0].Type === 'Text'
            || data.fields[0].Type === 'TextArea'
            || data.fields[0].Type === 'Dropdown'
            || data.fields[0].Type === 'DateTime') {
            data.FormData = WorkflowDesignerCommon.toJSON('{ "":"' + (value === null ? '' : value) + '"}');
          } else if (data.fields[0].Type === 'Json'
            || data.fields[0].Type === 'Checkbox'
            || data.fields[0].Type === 'MultiSelect'
            || data.fields[0].Type === 'Number'
          ) {
            data.FormData = WorkflowDesignerCommon.toJSON('{ "":' + value + '}');
          } else {
            data.FormData = WorkflowDesignerCommon.toJSON(value);
          }
        } else {
          data.FormData = WorkflowDesignerCommon.toJSON(value);
        }

        data.fields.forEach(function (field) {
          if (field.Type === 'Json') {
            data.FormData[field.Name] = data.FormData[field.Name] != undefined ? WorkflowDesignerCommon.toCompactJSON(WorkflowDesignerCommon.toString(data.FormData[field.Name])) : null;
          } else if (field.Type === 'Dropdown' && data.FormData[field.Name] !== null && typeof data.FormData[field.Name] !== 'string') {
            data.FormData[field.Name] = WorkflowDesignerCommon.toString(data.FormData[field.Name]);
          }
        });

        if (me.editor) {
          me.editor.destroy();
          delete me.editor;
        }

        // setTimeout(function(){
        //     methods.renderJSONFields();
        // });
      } else {

        var formData = methods.extractFormData();
        var value;

        if (data.FormData.hasOwnProperty('')) {
          var singleValue = formData[''];
          value = methods.extractSingleValue(singleValue);
        } else {
          value = WorkflowDesignerCommon.toString(formData);
        }

        if (me.editors) {
          for (var editor in me.editors) {
            me.editors[editor].destroy();
            delete me.editors[editor];
          }
          delete me.editors;
        }

        // TODO wtf
        setTimeout(function () {
          methods.renderEditor(value);
        }, 1);
      }
    }

    methods.extractSingleValue = function (singleValue) {
      var value = undefined;
      var fieldType = data.fields[0].Type;
      if (typeof singleValue == 'string' || fieldType == 'DateTime') {
        value = WorkflowDesignerCommon.toString(singleValue);

        value = value.indexOf('"') === 0 ? value.substring(1) : value;

        value = value.lastIndexOf('"') === value.length - 1 ? value.substring(0, value.length - 1) : value;

      } else {
        value = WorkflowDesignerCommon.toString(singleValue);
      }
      return value;
    }

    methods.onSave = function () {
      var value = undefined;
      var isValid = true;

      if (!data.formMode) {
        value = me.editor.getValue();
        me.onSuccess(WorkflowDesignerCommon.toCompactJSON(value));
        me.onClose(true);
      } else {
        this.$refs && this.$refs.form && this.$refs.form.validate(function (valid) {
          isValid = valid;
        }).then(() => {
          if (isValid) {
            var formData = methods.extractFormData();
            if (formData.hasOwnProperty('')) {
              var field = data.fields[0];
              var singleValue = formData[''];
              value = methods.extractSingleValue(singleValue);

              if ((field.Type === 'DateTime' || field.Type === 'Date' || field.Type === 'Time') && formData [field.Name] === null) {
                value = '';
              }
            } else {
              value = WorkflowDesignerCommon.toString(formData);
            }
          }

          if (isValid) {
            me.onSuccess(WorkflowDesignerCommon.toCompactJSON(value));
            me.onClose(true);
          }
        })
      }
    };

    methods.onClose = function () {
      me.onClose(true);
    };

    methods.onFormat = function () {
      var value = me.editor.getValue();
      me.editor.setValue(WorkflowDesignerCommon.toPrettyJSON(value));
      me.editor.clearSelection();
    };

    methods.onHideEvent = function () {
      if (me.editor) {
        me.editor.destroy();
        delete me.editor;
      }

      if (me.editors) {
        for (var editor in me.editors) {
          me.editors[editor].destroy();
          delete me.editors[editor];
        }
        delete me.editors;
      }
    }
  }
</script>
