<h3>{{ labels.Title }}</h3>
<el-form ref="form"
         :model="FormData"
         class="WorkflowDesignerWindowForm"
         label-position="top"
         label-width="150px">
  <div class="SettingsWithPadding">
    <div class="el-form--inline el-form--label-top">
      <el-form-item :label="labels.Name" :rules="requiredRule(ActivityRules)" class="el-form-item" prop="Name" style="flex-grow: 1;">
        <el-input v-model="FormData.Name" :placeholder="labels.Name" :readonly="readonly"></el-input>
      </el-form-item>
      <el-form-item v-if="expertMode" :label="labels.State" class="el-form-item" prop="State" style="flex-grow: 1;">
        <el-input v-model="FormData.State" :placeholder="labels.State" :readonly="readonly"></el-input>
      </el-form-item>
    </div>
    <el-form-item v-if="expertMode" size="small">
      <el-checkbox v-model="FormData.IsInitial" :disabled="readonly" :label="labels.IsInitial" name="type"
                   @change="onInitialChange"></el-checkbox>
      <el-checkbox v-model="FormData.IsForSetState" :disabled="readonly" :label="labels.IsForSetState" name="type"></el-checkbox>
      <el-checkbox v-model="FormData.IsAutoSchemeUpdate" :disabled="readonly" :label="labels.IsAutoSchemeUpdate" name="type"></el-checkbox>
    </el-form-item>
  </div>

  <div style="margin-bottom: 10px">
    <h4 class="WorkflowDesignerTitleWithCreate Underline SettingsHeader" style="margin-bottom: 17px;">
      {{ labels.Transition }}
      <a v-if="!readonly"
         @click="addRow(Transitions.all,
                {condition: {Type: 'Expression',Expression:null, Action: {ActionParameter:null}}, Classifier: 'NotSpecified'})">{{ ButtonTextCreate }}</a>
    </h4>
    <div style="margin-left: 20px;">
      <table class="WorkflowDesignerTable">
        <tr>
          <th></th>
          <th style="width: 160px;">{{ labels.ConditionType }}</th>
          <th style="flex-grow: 1;">{{ labels.Condition }}</th>
          <th style="flex-grow: 1;"></th>
          <template v-if="expertMode">
            <th v-if="expertMode" style="width: 100px;">{{ labels.ResultOnPreExecution }}</th>
            <th v-if="expertMode" style="width: 150px;">{{ labels.Classifier }}</th>
          </template>
          <th style="width: 180px;">{{ labels.To }}</th>
        </tr>
        <template v-for="(transition, index) in Transitions?.all" :key="index">
          <tr>
            <td></td>
            <td>
              <el-select
                v-if="!!transition?.condition?.Type"
                v-model="transition.condition.Type"
                :class="validateField('Type', transition.condition) ? 'WorkflowDesignerInputError' : ''"
                :disabled="readonly"
                :title="validateField('Type', transition.condition)"
                filterable
                placeholder="">
                <el-option key="Action" :label="labels.ActionLabel" value="Action"></el-option>
                <el-option key="Expression" :label="labels.ExpressionLabel" value="Expression"></el-option>
              </el-select>
            </td>
            <td v-if="!!transition?.condition?.Type && transition.condition.Type == 'Action'">
              <el-select
                v-if="!!transition?.condition?.Action?.ActionName"
                v-model="transition.condition.Action.ActionName"
                :class="validateField('Action.ActionName', transition.condition) ? 'WorkflowDesignerInputError' : ''"
                :disabled="readonly"
                :title="validateField('Action.ActionName', transition.condition)"
                clearable
                filterable
                placeholder=""
                style="width: 100%;">
                <el-option v-for="item in conditions" :key="item" :label="item" :value="item"></el-option>
              </el-select>
            </td>
            <td v-if="!!transition?.condition?.Type && transition.condition.Type == 'Action'">
              <el-autocomplete v-model="transition.condition.Action.ActionParameter" :disabled="readonly" :fetch-suggestions="querySearch"
                               :placeholder="labels.Parameters"
                               style="width: 100%;"
                               @focus="setCurrentItem(transition)"></el-autocomplete>
            </td>
            <td v-if="!!transition?.condition?.Type && transition.condition.Type == 'Expression'" colspan="2">
              <el-input
                v-model="transition.condition.Expression"
                :class="validateField('Expression', transition.condition) ? 'WorkflowDesignerInputError' : ''"
                :readonly="readonly"
                :title="validateField('Expression', transition.condition)"
                style="width: 100%;">
              </el-input>
            </td>
            <td v-if="!!transition?.condition?.Type && transition.condition.Type == 'Always'" colspan="2"></td>
            <template v-if="expertMode">
              <td>
                <el-select
                  v-model="transition.condition.ResultOnPreExecution"
                  :disabled="readonly"
                  filterable
                  placeholder=""
                  clearable
                  style="width: 100%;">
                  <el-option key="True" :value="true" label="True"></el-option>
                  <el-option key="False" :value="false" label="False"></el-option>
                </el-select>
              </td>
              <td>
                <el-select
                  v-model="transition.Classifier"
                  :disabled="readonly"
                  style="width: 100%;">
                  <el-option v-for="key in Object.keys(labels.ClassifierValues)"
                             :key="key" :label="labels.ClassifierValues[key]" :value="key"></el-option>
                </el-select>
              </td>
            </template>
            <td>
              <el-select
                v-model="transition.activity"
                :class="validateField('activity', transition) ? 'WorkflowDesignerInputError' : ''"
                :disabled="readonly"
                :title="validateField('activity', transition)"
                filterable
                placeholder=""
                style="width: 100%;">
                <el-option v-for="item in activities" :key="item.Name" :label="item.Name" :value="item.Name"></el-option>
              </el-select>
            </td>
            <td :style="!readonly ? 'width: 94px;' : 'width: 42px;'">
              <el-button-group>
                <el-button
                  :class="'WorkflowDesignerTableCodeActionsButton ' + (editItem == transition ? 'is-active' : '')"
                  @click="transition.condition.Type == 'Action' ? showjson('Action.ActionParameter', transition.condition, {name: transition.condition.Action.ActionName ,type: ['Condition']}) : showjson('Expression', transition.condition, {expression: true})"></el-button>
                <el-button v-if="!readonly" class="WorkflowDesignerTableDeleteButton"
                           @click="removeRow(Transitions.all, index)"></el-button>
              </el-button-group>
            </td>
          </tr>
        </template>
        <tr>
          <td></td>
          <td>
            <el-button
              :plain="FormData.EnableOtherwise"
              :style="FormData.EnableOtherwise ? 'opacity: 1;' : 'opacity: 0.5;'"
              style="text-align: left; padding-left: 15px; padding-right: 35px;" type="primary"
              @click="FormData.EnableOtherwise = !FormData.EnableOtherwise"
            >
              Otherwise
              <el-checkbox v-model="FormData.EnableOtherwise" @click.stop label=""></el-checkbox>
            </el-button>
          </td>
          <td></td>
          <td></td>
          <td v-if="expertMode"></td>
          <td v-if="expertMode">
            <el-select
              v-model="Transitions.otherwise.Classifier"
              :disabled="readonly"
              style="width: 100%;">
              <el-option v-for="key in Object.keys(labels.ClassifierValues)"
                         :key="key" :label="labels.ClassifierValues[key]" :value="key"></el-option>
            </el-select>
          </td>
          <td>
            <el-select
              v-if="FormData.EnableOtherwise"
              v-model="Transitions.otherwise.activity"
              :class="validateField('activity', Transitions.otherwise) ? 'WorkflowDesignerInputError' : ''"
              :disabled="!FormData.EnableOtherwise || readonly"
              :placeholder="labels.Parameters"
              :title="validateField('activity', Transitions.otherwise)"
              filterable
              style="width: 100%;">
              <el-option v-for="item in activities" :key="item.Name" :label="item.Name" :value="item.Name"></el-option>
            </el-select>
          </td>
          <td :style="!readonly ? 'width: 94px;' : 'width: 42px;'"></td>
        </tr>
      </table>
    </div>
  </div>
  <div style="margin-bottom: 10px;">
    <el-button v-if="!readonly && !itemHasComment" icon="IconComment" circle @click="showUserComment()"></el-button>
    <h4 v-if="itemHasComment" style="padding-bottom: 1px;border-bottom: 1px solid rgba(34,36,38,.15);">{{ labels.UserComment }}</h4>
    <el-input
      v-if="itemHasComment"
      v-model="FormData.UserComment"
      :placeholder="labels.UserComment"
      :rows="5"
      type="textarea"
    >
    </el-input>
  </div>
</el-form>
<div class="WorkflowDesignerButtons">
  <el-button link @click="expertMode = !expertMode">{{ expertMode ? SwitchToDefaultMode : SwitchToExpertMode }}</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 decisiontable_Data(me) {
    const {graph} = me;

    return {
      readonly: false,
      expertMode: false,
      actions: [],
      activities: [],
      activitiesStore: graph.data.Activities,
      conditions: graph.getConditionNames() || [],
      conditionsStore: graph.data.CodeActions,
      states: [],
      editItem: null,
      itemHasComment: false,
      FormData: {},
      Transitions: {},
      originalTransitions: {},
      originalName: null
    }
  }

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

    // TODO double check whole component

    methods.UpdateLanguage = function () {
      Object.assign(data, {
        labels: Object.assign(
          {},
          WorkflowDesignerConstants.ActivityFormLabel,
          WorkflowDesignerConstants.TransitionFormLabel,
          WorkflowDesignerConstants.DecisionTable),
        ButtonTextSave: WorkflowDesignerConstants.ButtonTextSave,
        ButtonTextCancel: WorkflowDesignerConstants.ButtonTextCancel,
        ButtonTextCreate: WorkflowDesignerConstants.ButtonTextCreate,
        ButtonTextDelete: WorkflowDesignerConstants.ButtonTextDelete,
        SwitchToDefaultMode: WorkflowDesignerConstants.SwitchToDefaultMode,
        SwitchToExpertMode: WorkflowDesignerConstants.SwitchToExpertMode,
      });
    }

    methods.UpdateLanguage();

    me.transitionManager = graph.GetComponentByType('WorkflowDesignerTransitionManager');
    me.activityManager = graph.GetComponentByType('WorkflowDesignerActivityManager');

    methods.GetTransitionsFrom = function (activityName) {
      var transitions = {
        all: [],
        otherwise: undefined
      };
      var foundTransitions = me.transitionManager.GetTransitionsFrom(activityName);
      foundTransitions.forEach(function (transition) {
        var item = transition.item;
        var ToName = transition.to.GetName();
        var condition = item.Conditions ? item.Conditions[0] : null;
        if (condition) {
          if (condition.Type.toLowerCase() === 'otherwise') {
            transitions.otherwise = {
              condition: WorkflowDesignerCommon.clone(condition),
              Classifier: item.Classifier,
              activity: ToName
            };
          } else {
            transitions?.all?.push?.({
              condition: WorkflowDesignerCommon.clone(condition),
              Classifier: item.Classifier,
              activity: ToName
            });
          }
        }
      });

      if (!transitions.all?.length) {
        transitions.all ??= []
        transitions.all.push({
          condition: {Action: {ActionParameter: null}, Expression: null, Type: 'Expression'},
          Classifier: WorkflowDesignerConstants.NotSpecified
        });
      }

      if (!transitions.otherwise) {
        transitions.otherwise = {
          condition: {Action: {}, Type: 'otherwise'},
          Classifier: WorkflowDesignerConstants.NotSpecified
        };
      }

      return transitions;
    };

    methods.updateActivitiesList = function (value) {
      data.activities = [];
      graph.data.Activities.forEach(function (element) {
        if (element == me.linkItem) //not add current activity
          return;
        data.activities.push(element);
      });
    }

    me.VueConfig.watch = {
      conditionsStore: function (val) {
        data.conditions = graph.getConditionNames();
      },
      activitiesStore: function (val) {
        methods.updateActivitiesList();
      },
    }

    methods.onUpdate = function (item) {
      var transitions = methods.GetTransitionsFrom(item.Name);
      data.transitions = transitions;
      var formdata = data.FormData;
      formdata.Name = item.Name;
      formdata.State = item.State;
      formdata.IsInitial = item.IsInitial;
      formdata.IsForSetState = item.IsForSetState;
      formdata.IsAutoSchemeUpdate = item.IsAutoSchemeUpdate;
      formdata.UserComment = item.UserComment;
      formdata.EnableOtherwise = !!transitions?.otherwise?.activity;
      data.Transitions = transitions;
      data.originalTransitions = WorkflowDesignerCommon.clone(transitions);
      data.originalName = item.Name;

      transitions?.all?.forEach?.(function (transition) {
        if (!transition?.condition?.Action) {
          transition.condition ??= {};
          transition.condition.Action = {};
        }
      });

      if (!transitions?.otherwise?.condition?.Action) {
        transitions.otherwise ??= {};
        transitions.otherwise.condition ??= {};
        transitions.otherwise.condition.Action = {};
      }

      me.linkItem = item;
      me.activityControl = me.activityManager.find(item.Name);
      data.originalItem = WorkflowDesignerCommon.clone(formdata);
      data.prevName = item.Name;
      data.readonly = graph.Settings.readonly;
      data.actions = graph.getActionNames();
      methods.updateActivitiesList();
      data.itemHasComment = formdata.UserComment != null && formdata.UserComment.length > 0;

      if ((formdata.State)
        || (transitions.all.find(item => item.Classifier && item.Classifier !== WorkflowDesignerConstants.NotSpecified))
        || (transitions.all.find(item => typeof (item.condition.ResultOnPreExecution) === 'boolean'))
        || (transitions.otherwise.Classifier && transitions.otherwise.Classifier !== WorkflowDesignerConstants.NotSpecified)) {
        data.expertMode = true;
      }
    };

    methods.showUserComment = function () {
      data.itemHasComment = true;
    }

    methods.onInitialChange = function () {
      var formdata = data.FormData;
      formdata.IsFinal = formdata.IsInitial ? false : formdata.IsFinal;
    };

    methods.onFinalChange = function () {
      var formdata = data.FormData;
      formdata.IsInitial = formdata.IsFinal ? false : formdata.IsInitial;
    };

    methods.setCurrentItem = function (item) {
      this.currentItem = item;
    };
    methods.querySearch = function (queryString, cb) {
      if (data.readonly)
        return cb([]);

      var res = graph.getAutoCompleteSuggestions2('actionparameter', this.currentItem.ActionName, queryString);
      cb(res);
    };

    methods.getFieldRules = function (field) {
      var res = [{required: true, message: WorkflowDesignerConstants.FieldIsRequired, trigger: 'blur'}];

      if (field === 'Name') {
        var validator = function (rule, value, callback) {
          var isValid = true;
          graph.data.Transitions.forEach(function (a) {
            if (a != me.linkItem && a.Name == value) {
              isValid = false;
            }
          });

          if (isValid) {
            callback();
          } else {
            callback(new Error(rule.message));
          }
        };
        res.push({validator: validator, message: WorkflowDesignerConstants.FieldMustBeUnique});
      }
      return res;
    };

    methods.validateField = function (name, item) {
      if (!item || !name) {
        console.warn(name, item)
        return;
      }


      if (name !== 'Name' && name !== 'Actor.Name' && name !== 'Type' && name !== 'Action.ActionName' && name !== 'Expression' && name !== 'activity')
        return;

      if (name === 'activity' && item.Type === 'Otherwise' && !data.FormData.EnableOtherwise) {
        return;
      }

      if (!WorkflowDesignerCommon.getValueByPropertyName(item, name)) {
        return WorkflowDesignerConstants.FieldIsRequired;
      }

      if (name === 'Type') {
        var conditions = data.FormData.Conditions;
        var labels = data.labels;
        if (item.Type === 'Always') {
          return labels.AlwaysConditionIsIllegal;
        }

        if (item.Type === 'Otherwise' && conditions.filter(function (c) {
          return c.Type == item.Type
        }).length > 1) {
          return labels.OtherwiseConditionShouldBeSingle;
        }
      }
    };

    methods.ActivityRules = function (res) {
      //validate on unique Activity name
      var validator = function (rule, value, callback) {
        var isValid = true;
        graph.data.Activities.forEach(function (a) {
          if (a != me.linkItem && a.Name == value) {
            isValid = false;
          }
        });

        if (isValid) {
          callback();
        } else {
          callback(new Error(rule.message));
        }
      };

      res.push({validator: validator, message: WorkflowDesignerConstants.FieldMustBeUnique});

      return res;
    };
    methods.addRow = function (items, item) {
      items.push(item || {});
    };

    methods.removeRow = function (items, index) {
      items.splice(index, 1);
    };

    methods.showjson = function (name, item, params) {
      data.editItem = item;
      me.editItem = item;

      var onSuccess = function (value) {
        if (me.editItem) {
          WorkflowDesignerCommon.setValueByPropertyName(me.editItem, name, value);
          data.editItem = undefined;
          delete me.editItem;
        }
      };

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

      var value = WorkflowDesignerCommon.getValueByPropertyName(item, name);
      data.jsonform = me.showjson(value, params, onSuccess, onClose);
    };

    methods.validate = function () {
      var validateFunc = methods.validateField;
      var transitions = data.Transitions;

      if (Array.isArray(transitions?.all) && transitions?.all?.length === 0) {
        data.showconditionerror = WorkflowDesignerConstants.TransitionFormLabel.ConditionsListShouldNotBeEmpty;
        return false;
      }

      for (var i = 0; i < transitions?.all?.length; i++) {
        var condition = transitions.all[i].condition;
        if (validateFunc('Type', condition) ||
          (condition.Type === 'Action' && validateFunc('Action.ActionName', condition)) ||
          (condition.Type === 'Expression' && validateFunc('Expression', condition)))
          return false;
        if (validateFunc('activity', transitions.all[i]))
          return false;
      }
      if (data.FormData.EnableOtherwise && validateFunc('activity', transitions.otherwise))
        return false;

      return true;
    };

    methods.saveTransition = function () {
      var FormData = data.FormData;
      var transitions = data.Transitions;
      var originalTransitions = data.originalTransitions;
      var originalName = data.originalName;

      if (FormData.Name !== originalName) {
        originalTransitions?.all?.forEach?.(function (originalTransition) {
          var controls = me.transitionManager.GetTransitionsFromTo(originalName, originalTransition.activity);
          if (controls && controls.length) {
            controls.forEach(function (control) {
              control.Delete();
            })
          }
        });
      } else {
        originalTransitions?.all?.forEach?.(function (originalTransition) {
          if (!transitions.all.some(function (current) {
            return originalTransition.activity === current.activity
          })) {
            var controls = me.transitionManager.GetTransitionsFromTo(FormData.Name, originalTransition.activity);
            if (controls && controls.length) {
              controls.forEach(function (control) {
                control.Delete();
              })
            }
          }
        });
      }

      transitions.all.forEach(function (item) {
        var controls = me.transitionManager.GetTransitionsFromTo(FormData.Name, item.activity);
        if (!controls || !controls.length) {
          var newTransition = me.transitionManager.CreateNewTransition(me.activityControl, me.activityManager.find(item.activity));
          newTransition.item.Conditions = [item.condition];
          newTransition.item.Classifier = item.Classifier;
        } else {
          controls[0].item.Conditions = [item.condition];
          controls[0].item.Classifier = item.Classifier;
        }
      });

      if (FormData.Name !== originalName && originalTransitions.otherwise) {
        var controls = me.transitionManager.GetTransitionsFromTo(originalName, originalTransitions.otherwise.activity);
        if (controls && controls.length) {
          controls.forEach(function (control) {
            control.Delete();
          })
        }
      }

      if (originalTransitions?.otherwise?.activity !== transitions?.otherwise?.activity || !data.FormData.EnableOtherwise) {
        var controls = me.transitionManager.GetTransitionsFromTo(FormData.Name, originalTransitions.otherwise.activity);
        if (controls && controls.length) {
          controls.forEach(function (control) {
            control.Delete();
          })
        }
      }

      if (!!data.FormData.EnableOtherwise) {
        var controls = me.transitionManager.GetTransitionsFromTo(FormData.Name, transitions.otherwise.activity);
        if (!controls || !controls.length) {
          var newTransition = me.transitionManager.CreateNewTransition(me.activityControl, me.activityManager.find(transitions.otherwise.activity));
          newTransition.item.Conditions = [{Type: 'Otherwise'}];
          newTransition.item.Classifier = transitions.otherwise.Classifier;
        } else {
          controls[0].item.Conditions = [transitions.otherwise.condition];
          controls[0].item.Classifier = transitions.otherwise.Classifier;
        }
      }
    }


    methods.onSave = function () {
      if (this.$refs) {
        WorkflowDesignerCommon.validateForms(this.$refs).then(isValid => {
          if (isValid && methods.validate()) {
            methods.saveTransition();
            me.onSuccess(data.FormData);
            me.onClose(true);
          }
        }).catch(() => { }) // Validation failed
      }
    };

    methods.onClose = function () {

      if (data.readonly) {
        me.onClose(true);
        return;
      }

      var originalItem = data.originalItem;
      var item = data.FormData;

      if (WorkflowDesignerCommon.deepCompare(originalItem, item)) {
        me.onClose(true);
      } else {
        me.showConfirm();
        return false;
      }
    };

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

    me.showConfirm = function () {
      methods.showConfirm({
        title: WorkflowDesignerConstants.DialogConfirmText,
        message: WorkflowDesignerConstants.CloseWithoutSaving,
        onSuccess: function () {
          methods.onCloseSave();
        }
      });
    }
  }
</script>
