<el-form class="mx-auto" class="WorkflowDesignerWindowForm" style="height: calc(100% - 10px);" @drop="drop($event)">
  <el-tabs v-model="activeTab" id="ElementsTabs" style="height: 100%; display: flex; flex-direction: column">
    <el-input clearable v-model="search" prefix-icon="el-icon-search" size="medium"
              style="margin-bottom: 15px"
              @input="onSearch"
    ></el-input>
    <el-tab-pane :label="labels.Activities" name="Activities">
      <div v-for="(item, index) in activities" :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 :label="labels.Templates" name="Templates">
      <div v-for="(item, index) in templates" :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_Init(me) {
    me.VueConfig.methods.UpdateLanguage = function () {
      me.VueConfig.data = Object.assign(me.VueConfig.data, {
        labels: WorkflowDesignerConstants.Elements,
      });
    }

    me.VueConfig.methods.UpdateLanguage();
    const data = Object.assign(me.VueConfig.data, {
      activeTab: 'Activities',
      original: {},
      activities: [],
      templates: [],
      loading: true,
    });

    me.VueConfig.mounted = function () {
      me.addMoveHandlers($.find('#ElementsTabs > .el-tabs__header')[0]);
    }

    me.VueConfig.methods.onUpdate = function () {
      data.search = '';

      data.activities = [];
      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 (me.graph.data?.AdditionalParams) {
        const {InlinedSchemeCodes} = me.graph.data.AdditionalParams;

        me.graph.designer.customActivities?.forEach?.(item => {
          item.Class = 'Custom';
          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 =>
        me.VueConfig.methods.getLocalizationItem(
          item,
          item.Class === 'Custom' ? item.Type : item.Class
        ));

      data.original.activities = data.activities;

      const validateTemplates = templates => {
        const pluginsNames = me.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.original.templates
          = data.templates
          = validateTemplates(result);
        data.loading = false;
      }

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

    me.VueConfig.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;
        }
      }
    };

    me.VueConfig.methods.onSearch = function () {
      me.VueConfig.watch.options.handler();
    };

    me.VueConfig.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
      };

      if (item.Type === 'DecisionTable' || item.Type === 'Decision') {
        //decisions doesn't have state by default
        activity.State = null;
        activity.IsForSetState = false;
      }

      const setValue = (key, value) => {
        if (value) activity[key] = value;
      }

      item.Parameters?.forEach(({Name, DefaultValue}) => setValue(Name, DefaultValue));
      for (const key in item.DefaultValues) setValue(key, item.DefaultValues[key]);

      me.graph.CreateActivity(pos, activity);
    }

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

    me.VueConfig.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();

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

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

    me.VueConfig.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', me.VueConfig.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();
      });
    };

    me.VueConfig.methods.dragend = function (e) {
      this.targetStyle.opacity = 1;
      me.parentContainer.off('dragover.elementsbar');
      me.parentContainer.off('dragover', me.VueConfig.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);
      }
    };

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

    me.VueConfig.watch = {
      options: {
        handler: () => {
          const activeTab = data.activeTab.toLowerCase();
          const search = data.search.toLowerCase();
          const includes = str => !!str?.toLowerCase().includes(search);

          if (!search) {
            data[activeTab] = data.original[activeTab];
            return;
          }
          data[activeTab] = data.original[activeTab]
            ?.filter(el => includes(el.Title) || includes(el.Description))
        }
      },
    };
  }
</script>
