<el-form class="WorkflowDesignerWindowForm" style="height: calc(100% - 10px);" @drop="drop($event)">
  <el-tabs v-model="activeTab" id="ElementsTabs" :class="hasBpmn && 'wf-elements-tabs with-bpmn'"
           style="height: 100%; display: flex; flex-direction: column;">
    <el-input clearable v-model="search" prefix-icon="IconSearch" size="default"
              style="margin-bottom: 15px"></el-input>
    <el-tab-pane :label="labels.Activities" name="activities">
      <div v-for="(item, index) in getFiltered()" :key="index" :draggable="true" style="cursor:grab; overflow-y: auto;
        flex: 1;" @dblclick="createActivity(item)"
           @dragend="dragend($event)" @dragstart="dragstart(item, $event, 'activity')" @drop="drop($event)">
        <el-card body-style="padding:15px">
          <div class="ActivityTitle">
            <div style="display: flex">
              <div :class="'Icon RTLIcon ' + item.Class" style="opacity: 0.8"></div>
              <label> {{ item.Title }}</label>
            </div>
            <el-tooltip :content="item.Description" placement="right">
              <i class="Icon Info"></i>
            </el-tooltip>
          </div>
        </el-card>
      </div>
    </el-tab-pane>
    <el-tab-pane v-if="hasBpmn" :label="labels.BPMN" name="bpmnActivities">
      <div v-for="(item, index) in getFiltered()" :key="index" :draggable="true" style="cursor:grab; overflow-y: auto;
        flex: 1;" @dblclick="createActivity(item)"
           @dragend="dragend($event)" @dragstart="dragstart(item, $event, 'activity')" @drop="drop($event)">
        <el-card body-style="padding:15px">
          <div class="ActivityTitle">
            <div style="display: flex; align-items: center;">
              <div class="Icon RTLIcon BPMN" style="opacity: 0.8" v-html="icons[item.SVGTemplate]"></div>
              <label> {{ item.Title }}</label>
            </div>
            <el-tooltip :content="item.Description" placement="right">
              <i class="Icon Info"></i>
            </el-tooltip>
          </div>
        </el-card>
      </div>
    </el-tab-pane>
    <el-tab-pane :label="labels.Templates" name="templates">
      <div v-for="(item, index) in getFiltered()" :key="index" class="TemplateCard">
        <b v-if="item.Header">{{ item.Header }}</b>
        <div v-if="item.Title" :draggable="item.IsEnable" style="cursor:grab;" @dragend="dragend($event)"
             @dragstart="dragstart(item, $event, 'template')"
             @drop="drop($event)">
          <el-card body-style="padding:15px;">
            <el-tooltip :content="labels.PluginRequired + ' ' + item.Plugins" :disabled="item.IsEnable">
              <div :class="(item.IsEnable ? '' : 'disabledCard') +  ' ActivityTitle'">
                <label> {{ item.Title }}</label>
                <el-tooltip :content="item.Description" placement="right">
                  <i class="Icon Info"></i>
                </el-tooltip>
              </div>
            </el-tooltip>
          </el-card>
        </div>
      </div>
    </el-tab-pane>
  </el-tabs>
</el-form>

<script type="application/javascript">
  function elements_Data(me) {
    return {
      activeTab: 'activities',
      icons: WorkflowDesignerConstants.icons,
      search: '',
      activities: [],
      templates: [],
      hasBpmn: false,
      loading: true,
    }
  }

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

    methods.UpdateLanguage = function () {
      Object.assign(data, {
        labels: WorkflowDesignerConstants.Elements,
      });
    }

    methods.UpdateLanguage();

    me.VueConfig.mounted = function () {
      me.addMoveHandlers($.find('#ElementsTabs > .el-tabs__header')[0]);
    }
    methods.onUpdate = function () {
      data.search = '';
      data.activities = [];
      data.bpmnActivities = [];
      data.hasBpmn = false;

      data.activities.push({
        Title: data.labels.BasicActivity,
        Description: data.labels.BasicActivityDesc,
        DefaultValues: {
          Name: 'Activity',
          State: 'Activity',
          Annotations: []
        },
        Class: 'Basic'
      });

      data.activities.push({
        Title: data.labels.InitialActivity,
        Description: data.labels.InitialActivityDesc,
        IsInitial: true,
        IsFinal: false,
        DefaultValues: {
          Name: 'InitialActivity',
          State: 'InitialActivity',
          Annotations: []
        },
        Class: 'Initial'
      });

      data.activities.push({
        Title: data.labels.FinalActivity,
        Description: data.labels.FinalActivityDesc,
        IsInitial: false,
        IsFinal: true,
        DefaultValues: {
          Name: 'FinalActivity',
          State: 'FinalActivity',
          Annotations: []
        },
        Class: 'Final'
      });

      data.activities.push({
        Title: data.labels.InlineHeader,
        Description: data.labels.InlineHeader,
        IsAutoSchemeUpdate: false,
        IsForSetState: false,
        ActivityType: 'Inline',
        Class: 'Inline'
      });

      data.activities.push({
        Title: data.labels.Comment.Title,
        Description: data.labels.Comment.Description,
        DefaultValues: {
          Name: 'Comment',
          State: 'Comment',
        },
        Template: 'comment',
        SVGTemplate: 'comment',
        Class: 'Custom',
        Type: 'Comment'
      });

      if (graph.data?.AdditionalParams) {
        const {InlinedSchemeCodes} = graph.data.AdditionalParams;

        graph.designer.customActivities?.forEach?.(item => {
          item.Class = 'Custom';
          if (item.PluginName === 'BpmnPlugin') {
            data.hasBpmn = true;
            data.bpmnActivities.push(item);
            return;
          }
          data.activities.push(item);
        });

        InlinedSchemeCodes?.forEach?.(item => {
          data.activities.push({
            Title: item,
            Type: item,
            DefaultValues: {
              ActivityType: 'Inline',
              State: undefined,
              SchemeCode: item,
              Annotations: []
            },
            Class: 'Inline'
          });
        });
      }

      data.activities.forEach(item =>
        methods.getLocalizationItem(
          item,
          item.Class === 'Custom' ? item.Type : item.Class
        ));

      const validateTemplates = templates => {
        const pluginsNames = graph.designer.getpluginsnames();
        const hasInPlugins = name => pluginsNames?.includes(name.trim())

        templates
          .filter(item => !item.hasOwnProperty('Header'))
          .forEach(item => {
            const pluginsArr = item.Plugins?.split(',');
            item.IsEnable = pluginsArr?.every(hasInPlugins) ?? true;
          });
        return templates;
      };

      const onLoad = result => {
        data.templates = validateTemplates(result);
        data.loading = false;
      }

      graph.designer.loadFile('library.json',
        data => onLoad(typeof data === 'string' ? JSON.parse(data) : data),
        () => onLoad(Array.from(WFELibrary))
      );
    };

    methods.getLocalizationItem = function (item, key) {
      if (data.labels[key] != undefined) {
        if (data.labels[key].Title != undefined) {
          item.Title = data.labels[key].Title;
        }
        if (data.labels[key].Description != undefined) {
          item.Description = data.labels[key].Description;
        }
      }
    };

    methods.createActivity = function (item, pos) {
      var activity = {
        Name: item.Type,
        IsInitial: item.IsInitial == true,
        IsFinal: item.IsFinal == true,
        State: item.Type,
        ActivityType: item.ActivityType,
        Annotations: [
          {JsonValue: item.Type, Name: '__customtype'}
        ],
        Template: item.Template,
        SVGTemplate: item.SVGTemplate
      };

      const setValue = (key, value) => {
        if (typeof value !== 'undefined') activity[key] = value
      }

      const customActivity = graph.GetCustomActivityByType(item.Type);

      for (const parameter of item.Parameters ?? []) {
        if (typeof customActivity !== 'undefined' &&  (customActivity?.OrdinaryActivityParameters?.includes(parameter.Name) ?? false)) {
          continue;
        }

        setValue(parameter.Name, parameter.DefaultValue);
        activity.Annotations.push({
          Name: parameter.Name,
          JsonValue: parameter.DefaultValue
        });
      }

      for (const key in item.DefaultValues) {
        setValue(key, item.DefaultValues[key])
      }

      graph.CreateActivity(pos, activity);
    }

    methods.savePos = function (e) {
      me.lastPos = e.originalEvent
    }

    methods.insertScheme = function (item, pos) {
      var e = me.lastPos;
      var loadingSpinner = $('<div class=\'WorkflowDesignerWindowLoaderOverlay Compact\'><div class=\'cv-spinner\'><span class=\'spinner\'></span></div></div>')
      $('body').append(loadingSpinner);
      loadingSpinner.css('left', e.pageX + 'px');
      loadingSpinner.css('top', e.pageY + 'px');
      loadingSpinner.show();

      graph.insertSchemeFromLibrary(item.File, pos, function () {
        loadingSpinner.remove()
      });
    }

    me.dragover = function (e) {
      me.pageX = e.pageX;
      me.pageY = e.pageY;
    }

    methods.dragstart = function (item, e, type) {
      this.draggingItem = item;
      this.draggingItemType = type;
      this.targetStyle = e.target.style;
      this.targetStyle.opacity = 0.6;
      me.parentContainer.on('dragover', methods.savePos);

      try {
        e.originalEvent.dataTransfer.setData('text/plain', 'anything'); //hack for drag&drop in FF
      } catch (e) {
      }

      window.addEventListener('dragover', me.dragover);
      me.parentContainer.on('dragover.elementsbar', function (e) {
        e.preventDefault();
      });
    };

    methods.dragend = function (e) {
      this.targetStyle.opacity = 1;
      me.parentContainer.off('dragover.elementsbar');
      me.parentContainer.off('dragover', methods.savePos);

      if (this.draggingItem !== undefined) {
        const e = me.lastPos;
        const offset = me.parentContainer.offset();
        const pos = {
          x: e.pageX - offset.left,
          y: e.pageY - offset.top
        };
        this.draggingItemType === 'activity'
          ? this.createActivity(this.draggingItem, pos)
          : this.insertScheme(this.draggingItem, pos);
        this.draggingItem = undefined;
        window.removeEventListener('dragover', me.dragover);
      }
    };

    methods.drop = function (e) {
      this.draggingItem = undefined;
      this.targetStyle.opacity = 1;
      me.parentContainer.off('dragover.elementsbar');
    };

    methods.getFiltered = function () {
      const search = data.search.toLowerCase();
      const list = data[data.activeTab];
      if (!search) return list;

      const includes = str => !!str?.toLowerCase().includes(search);
      return list?.filter(el => includes(el.Title) || includes(el.Description))
    };
  }
</script>
