<template>
  <w-dialog ref="dialogRef" :title="$t('re.processor.dialog.decisionTree.title')" :can-maximize="false" :maximized="true" body-padding="0px 2px 2px 2px">
    <w-graph v-model="modelValueRef" :vertex-defines="vertexDefines" :edge-defines="edgeDefines" @save="save"></w-graph>
  </w-dialog>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { $t, axios, Environment, NotifyManager, Formater, EnumTools } from 'platform-core';
import { AutoCompletionManager } from '@/views/shared/AutoCompletionManager';
import { UserDefinedFunctionsManager } from '@/views/shared/UserDefinedFunctionsManager';
import { PlaceHolder } from '@/utils/PlaceHolder';
import { EngineEnums } from '@/views/shared/enums/EngineEnums';

const dialogRef = ref();
const processorIdRef = ref();
const modelValueRef = ref();

const autoCompletionManager = new AutoCompletionManager();
const userDefinedFunctionsManager = new UserDefinedFunctionsManager();
const resourceAbstractsRef = ref();

const edgeDefines = [
  {
    type: 'EdgeConditionBranch',
    fromVertexType: 'Condition',
    toVertexType: null,
    getLabel: (value) => {
      return value.value || '';
    },
    getValue: (dom) => {
      if (dom) {
        return {
          valueType: dom.getAttribute('valueType') || '',
          value: dom.getAttribute('value') || '',
          commands: dom.getAttribute('commands') || '',
        };
      } else {
        return {
          valueType: 'java.lang.String',
          value: '',
          commands: '',
        };
      }
    },
    getFormFields: () => {
      return [
        {
          name: 'valueType',
          label: $t('re.graph.edge.conditionBranch.entity.valueType'),
          type: 'w-select',
          options: [
            { label: $t('java.lang.String'), value: 'java.lang.String' },
            { label: $t('java.lang.Boolean'), value: 'java.lang.Boolean' },
            { label: $t('java.math.BigDecimal'), value: 'java.math.BigDecimal' },
          ],
        },
        {
          name: 'value',
          label: $t('re.graph.edge.conditionBranch.entity.value'),
          type: 'w-text',
        },
        {
          name: 'commands',
          label: $t('re.graph.edge.conditionBranch.entity.commands'),
          type: 'w-code-mirror',
          lang: 'java',
          rows: 10,
          placeholder: true,
          lineWrap: true,
          lineBreak: true,
          autoCompletion: autoCompletionManager.autoCompletion(),
          userDefinedFunctions: userDefinedFunctionsManager.userDefinedFunctions(),
        },
      ];
    },
  },
];

const vertexDefines = [
  {
    type: 'Start',
    thumbnail: {
      shape: 'ellipse',
      label: $t('re.graph.vertex.start.label'),
      title: $t('re.graph.vertex.start.title'),
      rx: 8,
      ry: 8,
      strokeColor: 'black',
      strokeWidth: 1,
    },
    cell: {
      shape: 'ellipse',
      size: [50, 50],
    },
    getLabel: (value) => {
      return value.label;
    },
    getValue: (dom) => {
      if (dom) {
        return {
          label: dom.getAttribute('label') || '',
        };
      } else {
        return { label: $t('re.graph.vertex.start.label') };
      }
    },
    getFormFields: () => {
      return [
        {
          name: 'label',
          label: $t('description'),
          type: 'w-text',
        },
      ];
    },
  },
  {
    type: 'Condition',
    thumbnail: {
      shape: 'rhombus',
      label: $t('re.graph.vertex.condition.label'),
      title: $t('re.graph.vertex.condition.title'),
      strokeColor: 'black',
      strokeWidth: 1,
    },
    cell: {
      shape: 'rhombus',
      size: [120, 60],
    },
    getLabel: (value) => {
      return value.condition ? PlaceHolder.replace(value.condition) : '';
    },
    getValue: (dom) => {
      if (dom) {
        return {
          condition: dom.getAttribute('condition') || '',
        };
      } else {
        return {
          condition: '',
        };
      }
    },
    getFormFields: () => {
      return [
        {
          name: 'condition',
          label: $t('re.graph.vertex.condition.entity.condition'),
          type: 'w-code-mirror',
          lang: 'java',
          rows: 10,
          placeholder: true,
          lineWrap: true,
          lineBreak: false,
          autoCompletion: autoCompletionManager.autoCompletion(),
          userDefinedFunctions: userDefinedFunctionsManager.userDefinedFunctions(),
        },
      ];
    },
  },
  {
    type: 'Expression',
    thumbnail: {
      shape: 'rectangle',
      label: $t('re.graph.vertex.expression.label'),
      title: $t('re.graph.vertex.expression.title'),
      strokeColor: 'black',
      strokeWidth: 1,
    },
    cell: {
      shape: 'rectangle',
      size: [120, 60],
    },
    getLabel: (value) => {
      let html = '';
      html += '<div style="text-align:center;">' + PlaceHolder.replace(value.expression || '') + '</div>';
      html += '<hr size="0.5"/>';
      html += '<div style="text-align:left;">' + PlaceHolder.replace(value.commands || '') + '</div>';
      return html;
    },
    getValue: (dom) => {
      if (dom) {
        return {
          expression: dom.getAttribute('expression') || '',
          commands: dom.getAttribute('commands') || '',
        };
      } else {
        return {
          expression: '',
          commands: '',
        };
      }
    },
    getFormFields: () => {
      return [
        { name: 'expression', label: $t('re.graph.vertex.expression.entity.expression'), type: 'w-text' },
        {
          name: 'commands',
          label: $t('re.graph.vertex.expression.entity.commands'),
          type: 'w-code-mirror',
          lang: 'java',
          rows: 10,
          placeholder: true,
          lineWrap: true,
          lineBreak: true,
          autoCompletion: autoCompletionManager.autoCompletion(),
          userDefinedFunctions: userDefinedFunctionsManager.userDefinedFunctions(),
        },
      ];
    },
  },
  {
    type: 'ResourceAbstract',
    thumbnail: {
      shape: 'ellipse',
      label: $t('re.graph.vertex.resourceAbstract.label'),
      title: $t('re.graph.vertex.resourceAbstract.title'),
      rx: 11,
      ry: 6,
      strokeColor: 'black',
      strokeWidth: 1,
    },
    cell: {
      shape: 'ellipse',
      size: [120, 60],
    },
    getLabel: (value) => {
      const resourceAbstract = findResourceAbstractById(value.resourceAbstractId);
      if (resourceAbstract) {
        return resourceAbstract.name + '(V' + resourceAbstract.version + ')';
      }
      return '';
    },
    getValue: (dom) => {
      if (dom) {
        const code = dom.getAttribute('code');
        const version = dom.getAttribute('version');
        const resourceAbstract = findResourceAbstractByCodeAndVersion(code, version);
        if (resourceAbstract) {
          return {
            resourceAbstractId: resourceAbstract.id,
          };
        } else {
          return {
            resourceAbstractId: '',
          };
        }
      } else {
        return {
          resourceAbstractId: '',
        };
      }
    },
    setValue: (dom, value) => {
      const resourceAbstract = findResourceAbstractById(value.resourceAbstractId);
      if (resourceAbstract) {
        dom.setAttribute('code', resourceAbstract.code);
        dom.setAttribute('version', resourceAbstract.version);
      } else {
        dom.setAttribute('code', '');
        dom.setAttribute('version', '');
      }
    },
    getFormFields: () => {
      return [
        {
          name: 'resourceAbstractId',
          label: $t('re.graph.vertex.resourceAbstract.entity.resourceAbstractId'),
          type: 'w-grid-select',
          displayValue: (args) => {
            return args.data.name + '(V' + args.data.version + ')';
          },
          grid: {
            title: $t('re.graph.vertex.resourceAbstract.entity.resourceAbstractId'),
            denseBody: true,
            hideBottom: true,
            configButton: true,
            checkboxSelection: false,
            tree: true,
            treeIcon: (row) => {
              if (row.type === 'FOLDER') {
                return { name: 'folder', color: 'amber' };
              } else if (row.type === 'MODEL') {
                return { name: 'bi-boxes' };
              } else if (row.type === 'SCORE_CARD') {
                return { name: 'bi-card-list' };
              } else {
                return { name: row.icon };
              }
            },
            dataUrl: Environment.apiContextPath('/api/re/resource'),
            pageable: false,
            sortBy: ['type', 'namec', '-lastModifyDate'],
            toolbarConfigure: { noIcon: false },
            toolbarActions: ['refresh', 'expand'],
            columns: [
              { width: '100%', name: 'name', label: $t('name') },
              {
                width: 80,
                name: 'type',
                label: $t('type'),
                format: (value, row) => {
                  if (value !== 'FOLDER') {
                    return EngineEnums.ResourceType.formater(value);
                  }
                },
              },
              { width: 60, name: 'version', label: $t('version') },
              {
                width: 80,
                name: 'status',
                label: $t('status'),
                align: 'center',
                format: EngineEnums.DeployStatus.formater,
              },
            ],
          },
        },
      ];
    },
  },
];

const findResourceAbstractById = (id) => {
  for (const item of resourceAbstractsRef.value) {
    if (item.id === id) {
      return item;
    }
  }
  return null;
};

const findResourceAbstractByCodeAndVersion = (code, version) => {
  for (const item of resourceAbstractsRef.value) {
    if (item.code === code && item.version.toString() === version) {
      return item;
    }
  }
  return null;
};

const open = async (parameterId, processorId) => {
  autoCompletionManager.load(Environment.apiContextPath('/api/re/common/autoCompletionByParameterId/' + parameterId));
  userDefinedFunctionsManager.load();

  processorIdRef.value = processorId;
  // 获取资源摘要
  const resourceAbstractResponse = await axios.get(Environment.apiContextPath('/api/re/resource/getAllReleasableResourceAbstract'));
  resourceAbstractsRef.value = resourceAbstractResponse?.data;

  // 获取决策树 graph xml
  const graphResponse = await axios.get(Environment.apiContextPath('api/re/model/parameter/processor/getDecisionTreeById/' + processorIdRef.value));
  modelValueRef.value = graphResponse?.data;

  // 显示对话框
  dialogRef.value.show();
};

const close = () => {
  dialogRef.value.hide();
};

const save = (xml) => {
  axios.post(Environment.apiContextPath('api/re/model/parameter/processor/saveDecisionTreeById/' + processorIdRef.value), { xml }).then((response) => {
    NotifyManager.info($t('operationSuccess'));
  });
};

defineExpose({
  open,
  close,
});

await EngineEnums.init();
</script>
