<template>
  <div>
    <q-splitter :model-value="100" unit="px" class="w-full h-full">
      <template #before>
        <q-tabs v-model="selectedTabRef" vertical>
          <q-tab name="processDefine" icon="mail" :label="$t('lcdp.bpm.tabs.processDefine')" />
          <q-tab name="processInstance" icon="mail" :label="$t('lcdp.bpm.tabs.processInstance')" />
          <q-tab name="task" icon="mail" :label="$t('lcdp.bpm.tabs.task')" />
        </q-tabs>
      </template>
      <template #after>
        <q-tab-panels v-model="selectedTabRef" animated swipeable vertical transition-prev="jump-up" transition-next="jump-up" keep-alive>
          <q-tab-panel name="processDefine">
            <w-grid
              ref="processDefineGridRef"
              :title="$t('lcdp.bpm.processDefine.grid.title')"
              :checkbox-selection="true"
              :data-url="Environment.apiContextPath('/api/flowable/process')"
              :pageable="true"
              :pagination="{ sortBy: 'lastModifyDate', descending: true }"
              :query-form-cols-num="4"
              :query-form-fields="[
                { name: 'key', label: $t('code'), type: 'text' },
                { name: 'name', label: $t('name'), type: 'text' },
                { name: 'status', label: $t('status'), queryOperator: 'equals', type: 'select', clearable: true, options: Options.enum(ProcessStatusEnum) },
              ]"
              :toolbar-actions="[
                'query',
                'separator',
                'refresh',
                'separator',
                'add',
                'clone',
                {
                  extend: 'edit',
                  enableIf: (selecteds) => {
                    if (selecteds && selecteds.length > 0) {
                      const selected = selecteds[0];
                      if ('SKETCH' === selected.status) {
                        return true;
                      }
                    }
                    return false;
                  },
                },
                {
                  extend: 'remove',
                  enableIf: (selecteds) => {
                    if (selecteds && selecteds.length > 0) {
                      const selected = selecteds[0];
                      if ('SKETCH' === selected.status) {
                        return true;
                      }
                    }
                    return false;
                  },
                },
                'separator',
                {
                  name: 'design',
                  label: $t('lcdp.bpm.processDefine.grid.toolbar.design'),
                  icon: 'bi-brush',
                  enableIf: (selecteds) => {
                    if (selecteds && selecteds.length > 0) {
                      const selected = selecteds[0];
                      if ('SKETCH' === selected.status) {
                        return true;
                      }
                    }
                    return false;
                  },
                  click: (selecteds: object[]) => {
                    if (selecteds && selecteds.length > 0) {
                      const selected = selecteds[0];
                      let title = $t('lcdp.bpm.designer.dialog.title.prefix');
                      title += ' - ' + selected.name;
                      title += selected.version ? ' (' + selected.version + ')' : '';
                      processDesignerDialogRef.open(title, selected.id);
                    }
                  },
                },
                {
                  name: 'deployment',
                  label: $t('lcdp.bpm.processDefine.grid.toolbar.deployment'),
                  icon: 'bi-arrow-up-circle',
                  enableIf: (selecteds) => {
                    if (selecteds && selecteds.length > 0) {
                      const selected = selecteds[0];
                      if ('SKETCH' === selected.status) {
                        return true;
                      }
                    }
                    return false;
                  },
                  click: (selecteds: object[]) => {
                    DialogManager.confirm($t('lcdp.bpm.processDefine.grid.toolbar.deployment.tip'), () => {
                      axios.post(Environment.apiContextPath('api/flowable/process/deploy/') + selecteds[0].id).then(() => {
                        processDefineGridRef.refresh();
                        NotifyManager.success();
                      });
                    });
                  },
                },
                'separator',
                {
                  name: 'createProcessInstance',
                  label: $t('lcdp.bpm.processDefine.grid.toolbar.createProcessInstance'),
                  icon: 'bi-file-plus',
                  enableIf: (selecteds) => {
                    if (selecteds && selecteds.length > 0) {
                      const selected = selecteds[0];
                      if ('RELEASE' === selected.status) {
                        return true;
                      }
                    }
                    return false;
                  },
                  click: (selecteds) => {
                    if (selecteds && selecteds.length > 0) {
                      const selected = selecteds[0];
                      createProcessInstanceDialogRef.open(selected.key, selected.name);
                    }
                  },
                },
                {
                  name: 'queryProcessInstance',
                  label: $t('lcdp.bpm.processDefine.grid.toolbar.queryProcessInstance'),
                  icon: 'bi-list-ul',
                  enableIf: (selecteds) => {
                    if (selecteds && selecteds.length > 0) {
                      const selected = selecteds[0];
                      if ('SKETCH' != selected.status) {
                        return true;
                      }
                    }
                    return false;
                  },
                  click: (selecteds: object[]) => {
                    if (selecteds && selecteds.length > 0) {
                      const selected = selecteds[0];
                      selectedTabRef = 'processInstance';
                      nextTick(() => {
                        processInstanceGridRef.getQueryForm().setFieldValue('deployedId', selected.deployedId);
                        processInstanceGridRef.refresh();
                      });
                    }
                  },
                },
                'separator',
                'view',
                'separator',
                'export',
              ]"
              :columns="[
                { width: 150, name: 'key', label: $t('code') },
                {
                  width: '100%',
                  name: 'name',
                  label: $t('name'),
                  format: (value, row) => {
                    return Formater.dictionary(ProcessCategoryDictionaries)(row.key);
                  },
                },
                { width: 60, name: 'version', label: $t('version') },
                { width: 60, name: 'status', label: $t('status'), format: Formater.enum(ProcessStatusEnum) },
                { width: 250, name: 'deployedId', label: $t('lcdp.bpm.processDefine.grid.entity.deployId') },
                {
                  width: 90,
                  name: 'canClaimTask',
                  label: $t('lcdp.bpm.processDefine.grid.entity.canClaimTask'),
                  format: Formater.yesNo(),
                },
                { width: 100, name: 'lastModifier', label: $t('lastModifier') },
                { width: 110, name: 'lastModifyDate', label: $t('lastModifyDate'), format: Formater.dateOnly() },
              ]"
              :editor="{
                dialog: {
                  width: '600px',
                  height: '610px',
                },
                form: {
                  colsNum: 1,
                  fields: [
                    {
                      name: 'category',
                      label: $t('category'),
                      type: 'select',
                      defaultValue: 'SAMPLE',
                      options: Options.dictionary(ProcessCategoryDictionaries),
                      'onUpdate:modelValue': (value) => {
                        const form = processDefineGridRef.getEditorForm();
                        form.setFieldValue('key', value);
                        form.setFieldValue('name', Formater.dictionary(ProcessCategoryDictionaries)(value));
                      },
                    },
                    {
                      name: 'key',
                      label: $t('code'),
                      type: 'text',
                      defaultValue: 'SAMPLE',
                      readonlyIf: () => {
                        return true;
                      },
                    },
                    {
                      name: 'name',
                      label: $t('name'),
                      type: 'text',
                      required: true,
                      defaultValue: Formater.dictionary(ProcessCategoryDictionaries)('SAMPLE'),
                      readonlyIf: () => {
                        return true;
                      },
                    },
                    { name: 'description', label: $t('description'), type: 'textarea', rows: 1 },
                    { name: 'xml', label: $t('xml'), type: 'textarea' },
                    { name: 'status', label: $t('status'), type: 'text', defaultValue: 'SKETCH', hidden: true },
                    { name: 'canClaimTask', label: $t('lcdp.bpm.canClaimTask'), type: 'checkbox', defaultValue: true, rule: [] },
                  ],
                },
              }"
              :viewer="{
                panel: {
                  columnNum: 1,
                  fields: [
                    { name: 'id', label: $t('id') },
                    { name: 'category', label: $t('category') },
                    { name: 'key', label: $t('code') },
                    { name: 'name', label: $t('name'), format: Formater.none() },
                    { name: 'description', label: $t('description') },
                    { name: 'version', label: $t('version') },
                    { name: 'status', label: $t('status'), format: Formater.enum(ProcessStatusEnum) },
                    { name: 'deployedId', label: $t('lcdp.bpm.deployId') },
                    { name: 'canClaimTask', label: $t('lcdp.bpm.canClaimTask'), format: Formater.none() },
                    { name: 'lastModifier', label: $t('lastModifier') },
                    { name: 'lastModifyDate', label: $t('lastModifyDate'), format: Formater.none() },
                  ],
                },
              }"
            ></w-grid>
          </q-tab-panel>
          <q-tab-panel name="processInstance">
            <w-grid
              ref="processInstanceGridRef"
              :title="$t('lcdp.bpm.processInstance.grid.title')"
              :checkbox-selection="false"
              :data-url="Environment.apiContextPath('/api/flowable/process/query/instance')"
              :auto-fetch-data="false"
              :pageable="true"
              :pagination="{}"
              :query-form-cols-num="3"
              :query-form-fields="[
                { name: 'key', label: $t('lcdp.bpm.processInstance.grid.entity.processDefinitionKey'), type: 'text' },
                { name: 'name', label: $t('lcdp.bpm.processInstance.grid.entity.processDefinitionName'), type: 'text' },
                { name: 'deployedId', label: $t('lcdp.bpm.processInstance.grid.entity.processDefinitionId'), type: 'text' },
              ]"
              :toolbar-actions="[
                'query',
                'separator',
                'refresh',
                'separator',
                {
                  name: 'queryTask',
                  label: $t('lcdp.bpm.processInstance.grid.toolbar.queryTask'),
                  icon: 'bi-list-ul',
                  enableIf: (selecteds) => {
                    return selecteds && selecteds.length > 0;
                  },
                  click: (selecteds: object[]) => {
                    if (selecteds && selecteds.length > 0) {
                      const selected = selecteds[0];
                      selectedTabRef = 'task';
                      nextTick(() => {
                        taskGridRef.getQueryForm().setFieldValue('processInstanceId', selected.id);
                        taskGridRef.refresh();
                      });
                    }
                  },
                },
                {
                  name: 'variables',
                  label: $t('lcdp.bpm.task.grid.toolbar.variables'),
                  icon: 'bi-record',
                  enableIf: function (selecteds) {
                    return selecteds && selecteds.length > 0;
                  },
                  click: (selecteds) => {
                    if (selecteds && selecteds.length > 0) {
                      const selected = selecteds[0];
                      variableDialogRef.open(selected.id);
                    }
                  },
                },
                'separator',
                'view',
                'separator',
                'export',
              ]"
              :columns="[
                { name: 'id', label: $t('id') },
                { name: 'businessKey', label: $t('lcdp.bpm.processInstance.grid.entity.bussinessKey') },
                { name: 'startTime', label: $t('lcdp.bpm.processInstance.grid.entity.startTime'), format: Formater.dateOnly() },
                { name: 'startUserId', label: $t('lcdp.bpm.processInstance.grid.entity.startUserId') },
                { name: 'suspended', label: $t('lcdp.bpm.processInstance.grid.entity.suspended') },
                { name: 'processDefinitionKey', label: $t('lcdp.bpm.processInstance.grid.entity.processDefinitionKey') },
                { name: 'processDefinitionName', label: $t('lcdp.bpm.processInstance.grid.entity.processDefinitionName') },
                { name: 'processDefinitionId', label: $t('lcdp.bpm.processInstance.grid.entity.processDefinitionId') },
              ]"
              :editor="{
                dialog: {
                  width: '600px',
                  height: '610px',
                },
                form: {
                  colsNum: 1,
                  fields: [],
                },
              }"
              :viewer="{
                panel: {
                  columnNum: 1,
                  fields: [],
                },
              }"
            ></w-grid>
          </q-tab-panel>
          <q-tab-panel name="task">
            <w-grid
              ref="taskGridRef"
              :title="$t('lcdp.bpm.task.grid.title')"
              :checkbox-selection="false"
              :data-url="Environment.apiContextPath('/api/flowable/process/query/task')"
              :auto-fetch-data="false"
              :pageable="true"
              :pagination="{ sortBy: 'createTime', descending: true }"
              :query-form-cols-num="3"
              :query-form-fields="[
                { name: 'processInstanceId', label: $t('lcdp.bpm.task.grid.entity.processInstanceId'), type: 'text', queryOperator: 'equals' },
              ]"
              :toolbar-actions="[
                'query',
                'separator',
                'refresh',
                'separator',
                [
                  {
                    label: $t('operation'),
                  },
                  {
                    name: 'complete',
                    label: $t('lcdp.bpm.task.grid.toolbar.complete'),
                    enableIf: function (selecteds) {
                      return selecteds && selecteds.length > 0;
                    },
                    click: (selecteds) => {
                      if (selecteds && selecteds.length > 0) {
                        DialogManager.confirm($t('lcdp.bpm.task.grid.toolbar.complete.tip'), () => {
                          axios.post(Environment.apiContextPath('/api/flowable/process/operation/complete/') + selecteds[0].id).then(() => {
                            taskGridRef.refresh();
                            NotifyManager.success();
                          });
                        });
                      }
                    },
                  },
                  {
                    name: 'claim',
                    label: $t('lcdp.bpm.task.grid.toolbar.claim'),
                    enableIf: function (selecteds) {
                      return selecteds && selecteds.length > 0 && !selecteds[0].assignee;
                    },
                    click: (selecteds) => {
                      if (selecteds && selecteds.length > 0) {
                        DialogManager.confirm($t('lcdp.bpm.task.grid.toolbar.claim.tip'), () => {
                          axios.post(Environment.apiContextPath('/api/flowable/process/operation/claim/') + selecteds[0].id).then(() => {
                            taskGridRef.refresh();
                            NotifyManager.success();
                          });
                        });
                      }
                    },
                  },
                  {
                    name: 'unclaim',
                    label: $t('lcdp.bpm.task.grid.toolbar.unclaim'),
                    enableIf: function (selecteds) {
                      return selecteds && selecteds.length > 0 && selecteds[0].assignee;
                    },
                    click: (selecteds) => {
                      if (selecteds && selecteds.length > 0) {
                        DialogManager.confirm($t('lcdp.bpm.task.grid.toolbar.unclaim.tip'), () => {
                          axios.post(Environment.apiContextPath('/api/flowable/process/operation/unClaim/') + selecteds[0].id).then(() => {
                            taskGridRef.refresh();
                            NotifyManager.success();
                          });
                        });
                      }
                    },
                  },
                  {
                    name: 'jump',
                    label: $t('lcdp.bpm.task.grid.toolbar.jump'),
                    enableIf: function (selecteds) {
                      return selecteds && selecteds.length > 0;
                    },
                    click: (selecteds) => {
                      if (selecteds && selecteds.length > 0) {
                        jumpTaskDialogRef.open(selecteds[0].id);
                      }
                    },
                  },
                  {
                    name: 'terminate',
                    label: $t('lcdp.bpm.task.grid.toolbar.terminate'),
                    enableIf: function (selecteds) {
                      return selecteds && selecteds.length > 0;
                    },
                    click: (selecteds) => {
                      if (selecteds && selecteds.length > 0) {
                        DialogManager.confirm($t('lcdp.bpm.task.grid.toolbar.terminate.tip'), () => {
                          axios.post(Environment.apiContextPath('/api/flowable/process/operation/terminateProcessInstance/') + selecteds[0].id).then(() => {
                            taskGridRef.refresh();
                            NotifyManager.success();
                          });
                        });
                      }
                    },
                  },
                ],
                {
                  name: 'variables',
                  label: $t('lcdp.bpm.task.grid.toolbar.variables'),
                  icon: 'bi-record',
                  enableIf: function (selecteds) {
                    return selecteds && selecteds.length > 0;
                  },
                  click: (selecteds) => {
                    if (selecteds && selecteds.length > 0) {
                      const selected = selecteds[0];
                      variableDialogRef.open(selected.processInstanceId);
                    }
                  },
                },
                'separator',
                'view',
                'separator',
                'export',
              ]"
              :columns="[
                { name: 'id', label: $t('id') },
                { name: 'name', label: $t('name') },
                { name: 'owner', label: $t('lcdp.bpm.task.grid.entity.owner') },
                { name: 'assignee', label: $t('lcdp.bpm.task.grid.entity.assignee') },
                { name: 'createTime', label: $t('lcdp.bpm.task.grid.entity.createTime') },
                { name: 'claimTime', label: $t('lcdp.bpm.task.grid.entity.claimTime') },
                { name: 'processInstanceId', label: $t('lcdp.bpm.task.grid.entity.processInstanceId') },
              ]"
              :editor="{
                dialog: {
                  width: '600px',
                  height: '610px',
                },
                form: {
                  colsNum: 1,
                  fields: [],
                },
              }"
              :viewer="{
                panel: {
                  columnNum: 1,
                  fields: [],
                },
              }"
            ></w-grid>
          </q-tab-panel>
        </q-tab-panels>
      </template>
    </q-splitter>

    <ProcessDesigner ref="processDesignerDialogRef">
      <iframe ref="processDesignerIframeRef" src="#" style="width: 100%; height: 100%"></iframe>
    </ProcessDesigner>

    <CreateProcessInstanceDialog ref="createProcessInstanceDialogRef"></CreateProcessInstanceDialog>

    <VariableDialog ref="variableDialogRef"></VariableDialog>
    <JumpTaskDialog ref="jumpTaskDialogRef"></JumpTaskDialog>
  </div>
</template>
<script setup lang="ts">
import { ref, nextTick } from 'vue';
import { Environment, DialogManager, NotifyManager, axios, EnumTools, DictionaryTools, Formater, Options } from 'platform-core';
import ProcessDesigner from './ProcessDesigner.vue';
import CreateProcessInstanceDialog from './CreateProcessInstanceDialog.vue';
import VariableDialog from './VariableDialog.vue';
import JumpTaskDialog from './JumpTaskDialog.vue';

const selectedTabRef = ref('processDefine');
const processDefineGridRef = ref();
const processInstanceGridRef = ref();
const taskGridRef = ref();
const variableDialogRef = ref();
const jumpTaskDialogRef = ref();

const processDesignerDialogRef = ref();
const processDesignerIframeRef = ref();
const createProcessInstanceDialogRef = ref();

const ProcessStatusEnum = await EnumTools.fetch('io.sc.platform.flowable.enums.ProcessStatus');
const ProcessCategoryDictionaries = await DictionaryTools.fetch('WORK_FLOW');
</script>
