<i18n>
{
  "en": {
    "ProcessesCard": {
      "type": "Type",
      "actions": "Actions",
      "datetime": "Date and time",
      "tableTitle": "Processes",
      "DmnTableTitle": "Decision tables",
      "name": "Name",
      "id": "id",
      "noProcessesResult": "No Processes result",
      "confirmationMessage": "Are you sure you want to delete the process?",
      "ProcessTypes": {
        "import": "Import",
        "dmn": "Decisions table",
        "dataPrepare": "Data prepare",
        "route": "Routing",
        "interagencies": "Interdepartmental interaction",
        "baseProcess": "Base process"
      },
      "btn": {
        "createProcess": "New process",
        "createMZProcess": "Create mz process",
        "createTable": "New table",
        "generateTable": "Generate table",
        "openProcess": "Open base process"
      }
    },
    "surge": {
      "table": {
        "title": "Surge",
        "cols": {
          "interagency": "MZ",
          "process": "Process"
        }
      },
      "btn": {
        "create": "Add surge"
      }
    }
  },
  "ru": {
    "ProcessesCard": {
      "type": "Тип",
      "actions": "Действия",
      "datetime": "Дата и время",
      "tableTitle": "Процессы",
      "DmnTableTitle": "Таблицы решений",
      "name": "Наименование",
      "id": "Идентификатор",
      "noProcessesResult": "Нет результата по процессам",
      "confirmationMessage": "Вы уверены, что хотите удалить БП?",
      "ProcessTypes": {
        "import": "Импорт",
        "dmn": "Таблица решений",
        "dataPrepare": "Предподготовка данных",
        "route": "Маршрутизация",
        "interagencies": "Межведомственное взаимодействие",
        "baseProcess": "Базовый процесс"
      },
      "btn": {
        "createProcess": "Новый процесс",
        "createMZProcess": "Создать процесс МВЗ",
        "createTable": "Новая таблица",
        "generateTable": "Сгенерировать таблицу",
        "openProcess": "Открыть базовый процесс"
      }
    },
    "surge": {
      "table": {
        "title": "Волны",
        "cols": {
          "interagency": "Классы МЗ",
          "process": "Процесс"
        }
      },
      "btn": {
        "create": "Добавить волну"
      }
    }
  }
}
</i18n>

<template>
  <div
    class="q-pb-md q-mt-md"
    v-if="common.active === 'processes' && !loadingCard"
  >
    <a ref="downloadBpmn" />
    <q-card class="no-shadow q-gutter-y-md q-mx-md q-pb-lg no-border-radius">
      <div
        class="q-gutter-y-md bg-white q-px-lg q-pb-md q-pt-sm q-mt-md rounded-borders"
      >
        <div class="flex justify-end q-my-md row" style="width: 100%" v-if="canEdit">
          <div>
            <q-btn
              color="primary"
              text-color="white"
              v-if="state === 'inProgress'"
              @click="createMZProcess()"
              icon="add_box"
              :label="$t('ProcessesCard.btn.createMZProcess')"
              class="q-mr-md"
            >
            </q-btn>
            <q-btn
              color="primary"
              text-color="white"
              v-if="state === 'inProgress'"
              @click="addProcess('Process')"
              icon="add_box"
              :label="$t('ProcessesCard.btn.createProcess')"
              class="q-mr-md"
            >
            </q-btn>

            <q-btn
              @click="goToBpmnSchema('BaseApplicationProcess', 'processes')"
              icon="account_tree"
              color="primary"
              text-color="white"
              :label="$t('ProcessesCard.btn.openProcess')"
            >
            </q-btn>
          </div>
        </div>

        <q-expansion-item default-opened v-if="processes.length">
          <template v-slot:header>
            <q-item-section>
              <div class="text-h6">{{ $t('ProcessesCard.tableTitle') }}</div>
            </q-item-section>
          </template>

          <q-table
            :columns="columns"
            :data="processes"
            :pagination.sync="pagination"
            hide-bottom
            v-if="processes.length"
          >
            <template v-slot:header="props">
              <q-tr :props="props">
                <q-th v-for="col in props.cols" :key="col.name" :props="props">
                  {{ col.label }}
                </q-th>
                <q-th style="font-size: 16px; font-weight: 600">
                  {{ $t('ProcessesCard.actions') }}
                </q-th>
              </q-tr>
            </template>
            <template v-slot:body="props">
              <q-tr :props="props">
                <q-td v-for="col in props.cols" :key="col.name" :props="props">
                  {{ col.value }}
                </q-td>
                <q-td auto-width style="text-align: right">
                  <q-btn
                    icon="arrow_downward"
                    unelevated
                    @click="downloadBpmnSchema(props.row)"
                    text-color="primary"
                  >
                    <q-tooltip :delay="500"> Скачать</q-tooltip>
                  </q-btn>
                  <q-btn
                    v-if="canEdit"
                    color="white"
                    text-color="primary"
                    @click="goToBpmnSchema(props.row.id, 'processes')"
                    unelevated
                    icon="search"
                  >
                    <q-tooltip :delay="500">
                      Открыть в редакторе BPMN</q-tooltip
                    >
                  </q-btn>
                  <q-btn
                    v-if="state === 'inProgress' && canEdit"
                    icon="attach_file"
                    text-color="primary"
                    @click="addDocumentAttachment(props.row)"
                  >
                    <q-tooltip :delay="500"> Загрузить файл процесса</q-tooltip>
                  </q-btn>
                  <q-btn
                    v-if="state === 'inProgress' && canEdit"
                    @click="editProcessItem(props.row)"
                    icon="edit"
                    text-color="primary"
                  >
                    <q-tooltip :delay="500"> Редактировать</q-tooltip>
                  </q-btn>
                  <q-btn
                    v-if="canEdit"
                    text-color="negative"
                    @click="toggleDeleteConfim(props.row)"
                    icon="delete"
                    flat
                  >
                    <q-tooltip :delay="500"> Удалить</q-tooltip>
                  </q-btn>
                </q-td>
              </q-tr>
            </template>
          </q-table>
        </q-expansion-item>

        <div class="flex justify-end q-my-md row" style="width: 100%" v-if="canEdit">
          <div>
            <q-btn
              color="primary"
              text-color="white"
              v-if="state === 'inProgress'"
              @click="addProcess('Table')"
              icon="add_box"
              :label="$t('ProcessesCard.btn.createTable')"
            >
            </q-btn>
            <q-btn
              color="primary"
              text-color="white"
              v-if="state === 'inProgress'"
              @click="generateDmn"
              icon="post_add"
              class="q-ml-md"
              :label="$t('ProcessesCard.btn.generateTable')"
            >
            </q-btn>
          </div>
        </div>
        <q-expansion-item default-opened v-if="DmnTables.length">
          <template v-slot:header>
            <q-item-section>
              <div class="text-h6">{{ $t('ProcessesCard.DmnTableTitle') }}</div>
            </q-item-section>
          </template>
          <q-table
            :columns="columnsDMN"
            :data="DmnTables"
            :pagination.sync="pagination"
            hide-bottom
          >
            <template v-slot:header="props">
              <q-tr :props="props">
                <q-th v-for="col in props.cols" :key="col.name" :props="props">
                  {{ col.label }}
                </q-th>
                <q-th style="font-size: 16px; font-weight: 600">
                  {{ $t('services.ProcessesCard.serviceCode') }}
                </q-th>
                <q-th style="font-size: 16px; font-weight: 600">
                  {{ $t('ProcessesCard.actions') }}
                </q-th>
              </q-tr>
            </template>
            <template v-slot:body="props">
              <q-tr :props="props">
                <q-td v-for="col in props.cols" :key="col.name" :props="props">
                  {{ col.value }}
                </q-td>
                <q-td style="white-space: pre-wrap">
                  <span
                    style="display: inline-block; margin: 0 5px"
                    v-for="(item, index) in props.row.serviceCode"
                    :key="index"
                  >
                    <q-badge :color="goalColorMap[item]" :label="item" />
                  </span>
                </q-td>
                <q-td auto-width>
                  <q-btn
                    v-if="canEdit"
                    color="white"
                    text-color="primary"
                    @click="goToBpmnSchema(props.row.id, 'dmn')"
                    unelevated
                    icon="search"
                  />
                  <q-btn
                    icon="arrow_downward"
                    unelevated
                    v-if="get(props.row, 'attachment')"
                    @click="downloadBpmnSchema(props.row)"
                    text-color="primary"
                  >
                    <q-tooltip :delay="500"> Скачать</q-tooltip>
                  </q-btn>
                  <q-btn
                    v-if="state === 'inProgress' && canEdit"
                    icon="attach_file"
                    text-color="primary"
                    @click="addDocumentAttachment(props.row)"
                  >
                    <q-tooltip :delay="500"> Загрузить файл процесса</q-tooltip>
                  </q-btn>
                  <q-btn
                    v-if="state === 'inProgress' && canEdit"
                    @click="editProcessItem(props.row)"
                    icon="edit"
                    text-color="primary"
                  >
                    <q-tooltip :delay="500"> Редактировать</q-tooltip>
                  </q-btn>
                  <q-btn
                    v-if="canEdit"
                    text-color="negative"
                    @click="toggleDeleteConfim(props.row)"
                    icon="delete"
                    flat
                  >
                    <q-tooltip :delay="500"> Удалить</q-tooltip>
                  </q-btn>
                </q-td>
              </q-tr>
            </template>
          </q-table>
        </q-expansion-item>

        <div class="flex justify-end q-my-md row" style="width: 100%" v-if="canEdit">
          <div>
            <q-btn
              color="primary"
              text-color="white"
              v-if="state === 'inProgress'"
              @click="addProcess('Surge')"
              icon="add_box"
              :label="$t('surge.btn.create')"
            />
          </div>
        </div>
        <q-expansion-item default-opened v-if="surgeTables.length">
          <template v-slot:header>
            <q-item-section>
              <div class="text-h6">{{ $t('surge.table.title') }}</div>
            </q-item-section>
          </template>

          <q-table
            :columns="columnsSurge"
            :data="surgeTables"
            :pagination.sync="pagination"
            hide-bottom
          >
            <template v-slot:header="props">
              <q-tr :props="props">
                <q-th v-for="col in props.cols" :key="col.name" :props="props">
                  {{ col.label }}
                </q-th>
                <q-th/>
              </q-tr>
            </template>

            <template v-slot:body="props">
              <q-tr :props="props">
                <q-td v-for="col in props.cols" :key="col.name" :props="props">
                  <template v-if="col.name === 'parent'">
                    <span
                      style="display: inline-block; margin: 0 5px"
                      v-for="(item, index) in col.value"
                      :key="index"
                    >
                      <q-badge :color="goalColorMap[item]" :label="item" />
                    </span>
                  </template>
                  <template v-else >
                    {{ col.value }}
                  </template>
                </q-td>

                <q-td auto-width>
                  <q-btn
                    v-if="state === 'inProgress'"
                    @click="editProcessItem(props.row, 'Surge')"
                    icon="edit"
                    text-color="primary"
                  >
                    <q-tooltip :delay="500">
                      {{ $t('base.edit') }}
                    </q-tooltip>
                  </q-btn>
                  <q-btn
                    text-color="negative"
                    @click="toggleDeleteConfim(props.row, 'Surge')"
                    icon="delete"
                    flat
                  >
                    <q-tooltip :delay="500">
                      {{ $t('base.delete') }}
                    </q-tooltip>
                  </q-btn>
                </q-td>
              </q-tr>
            </template>
          </q-table>
        </q-expansion-item>
      </div>

      <ProcessFileUploadDialog
        v-if="openModal"
        :value.sync="openModal"
        :file.sync="attachFile"
        :schema-name="schemaName"
        :sub-title="documentForAttachment.name"
        :loading="attachmentLoading"
        @updateDocumentAttachment="updateDocumentAttachment"
        @hide="clearModel"
      />

      <q-dialog class="full-width" v-model="deleteConfim">
        <q-card class="no-shadow full-width">
          <q-card-section>
            <div class="text-h6">
              {{ $t('ProcessesCard.confirmationMessage') }}
            </div>
          </q-card-section>

          <q-card-actions align="right">
            <q-btn 
              @click="deleteProcess" 
              color="primary" 
              :label="$t('base.delete')"
             />

            <q-btn
              color="white"
              text-color="primary"
              outline
              @click="toggleDeleteConfim"
              :label="$t('base.undo')"
            />
          </q-card-actions>
        </q-card>
      </q-dialog>
    </q-card>

    <component
      v-if="formComponent"
      :common="common"
      :model="model"
      @commonModels="commonModels"
      :dialog-data="formModel"
      :is="formComponent"
    />
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import ProcessFileUploadDialog from './Processes/FileUploadDialog.vue';
import { saveFileViaLink } from '@utils/files';
import { BaseCardCommon } from '@/interfaces';
import {
  fetchAttachment,
  unlinkService,
  updateAttachment,
} from '@services/registry-service';
import { Service } from '@openapi/registry-service';
import get from 'lodash/get';
import cloneDeep from 'lodash/cloneDeep';
import { uploadBPMN, uploadDMN } from '@services/wf';
import { notifyError, notifySuccess } from '@utils/notify';
import { v4 } from 'uuid';

declare interface Process {
  id: string;
  hidden: boolean;
  modified: number;
  schema: string;
  name: string;
  type: string;
  // todo eslint rule
  // eslint-disable-next-line camelcase
  _service_id: string;
  version: string;
}

type Surge = {
  uuid: string, 
  interagency: string,
  parent: string[]
}

type Type = 'Process' | 'Table' | 'Surge'

@Component({
  components: {
    ProcessFileUploadDialog,
  },
  methods: {
    get,
  },
})
export default class ProcessesCard extends Vue {
  @Prop() model: any;
  @Prop() common!: BaseCardCommon;

  // todo fix null typings
  deleteConfim = false;
  deleteItem: any = null;
  formComponent = '';
  attachFile: File | null = null;
  attachedFileName = '';
  documentForAttachmentUUID: string | null = ''; // ?
  attachmentLoading = false;
  openModal = false;
  schemaName = 'Process';
  fetchingInProgress = {};
  documentForAttachment = null;
  formModel = {};
  pagination = {
    rowsPerPage: 0,
  };

  toggleDeleteConfim(item: any = null, type: Type = 'Process') {
    this.deleteConfim = !this.deleteConfim;

    if (type === 'Surge') {
      this.deleteItem = {
        id: item.uuid,
        schema: type
      }
    } else {
      this.deleteItem = item;
    }
  }

  async deleteProcess() {
    let schema = get(this.deleteItem, 'schema')

    let enty;
    let callableFilter;
    if (schema === 'Surge') {
      enty = 'interagencyWaves';
      callableFilter = (v: any) => v.uuid !== this.deleteItem.id
    } else {
      enty = schema === 'Table' ? 'tables' : 'processes';
      callableFilter = (v: any) => v.id !== this.deleteItem.id
    }

    // todo add service type (global)
    const service = {
      id: get(this.card, 'id'),
      modified: get(this.card, 'modified'),
      [enty]: [get(this.deleteItem, 'id')], // why [] ?
    };
    // service[type] = [get(this.deleteItem, 'id')];
    try {
      const { data: result } = await unlinkService(service as Service);
      this.card[enty] = this.card[enty].filter(callableFilter);
      this.card.modified = result.modified;
      this.$store.dispatch(
        'registryService/services/setCardForJson',
        this.card
      );
    } catch (e: any) {
      notifyError(e.message.toString());
    } finally {
      this.toggleDeleteConfim();
    }
  }

  async updateDocumentAttachment() {
    if (!this.attachFile) {
      return;
    }

    const extension = this.attachFile?.name.split('.').pop();

    try {
      switch (extension) {
        case 'bpmn':
          await uploadBPMN(this.attachFile);
          break;

        case 'dmn':
          await uploadDMN(this.attachFile);
          break;
      }
    } catch (e) {
      return;
    }

    try {
      const file = new File([this.attachFile], this.attachedFileName);
      this.attachmentLoading = true;
      const docUUID = this.documentForAttachmentUUID;
      await updateAttachment(this.schemaName, docUUID as string, '', [file]);
      notifySuccess('Файл успешно загружен');
    } catch (e) {
      notifyError(e.message.toString());
    } finally {
      this.attachmentLoading = false;
      this.openModal = false;
      this.documentForAttachmentUUID = null;
      this.documentForAttachment = null;
      this.attachedFileName = '';
    }
  }

  clearModel() {
    this.attachedFileName = '';
    this.attachFile = null;
  }

  // todo type, = Process?
  async downloadBpmnSchema(val: any) {
    if (!val) {
      console.warn('[Servise][Processes][goToBpmnSchema] Missing schema name');
      return;
    }
    try {
      const extension = val.schema === 'Process' ? 'bpmn' : 'dmn';
      const xml = await fetchAttachment(
        val.schema,
        val.id,
        `${val.name}.${extension}`,
        false
      );
      saveFileViaLink({
        anchor: this.$refs.downloadBpmn as HTMLAnchorElement,
        hrefData:
          'data:application/bpmn20-xml;charset=UTF-8,' +
          encodeURIComponent(xml),
        fileName: `${val.name}.${extension}`,
      });
    } catch (e) {
      notifyError(e.message.toString());
    }
  }

  // todo type, = Process?
  addDocumentAttachment(document: any) {
    this.schemaName = document.schema;
    this.documentForAttachment = document;
    this.documentForAttachmentUUID = document.id;
    this.attachedFileName = `${document.name}.${
      document.schema === 'Process' ? 'bpmn' : 'dmn'
    }`;
    this.openModal = true;
  }

  goToBpmnSchema(name: string, editorType: string) {
    if (!name) {
      console.warn('[Servise][Processes][goToBpmnSchema] Missing schema name');
      return;
    }
    this.$router.push({
      name: 'cards',
      params: {
        id: name,
        path: editorType,
      },
      query: {
        active: 'index',
        components: 'index',
        service: this.card.id,
      },
    });
  }

  fetchForm(template: string) {
    this.formComponent = this.$GlobalComponentImporter.registerComponent(
      template,
      `cards/services/`
    );
  }

  editProcessItem(row: Process, type: Type = 'Process') {
    let componentName;
    let schema;

    switch(type) {
      case 'Surge': {
        componentName = 'surge_dialog';
        schema = {
          SurgeDialog: { data: row }
        };

        break;
      }
      case 'Process':
      case 'Table':
      default: {
        componentName = 'process_dialog';
        schema = {
          ProcessDialog: {
            data: row
          }
        };
      }
    }

    this.fetchForm(componentName);
    this.commonModels(schema);
  }

  addProcess(val: Process | Type) {
    let componentName;
    let schema;

    switch(val) {
      case 'Surge': {
        componentName = 'surge_dialog';
        schema = {
          SurgeDialog: { data: 'createMode' }
        };

        break;
      }
      case 'Process':
      case 'Table':
      default: {
        componentName = 'process_dialog';
        schema = {
          ProcessDialog: {
            data: { mode: 'createMode', schema: val }
          }
        };
      }
    }

    this.fetchForm(componentName);
    this.commonModels(schema);
  }

  createMZProcess() {
    let schema;
    schema = {
      MvzDialog: {
        data: { mode: 'createMode'}
      }
    };
    this.fetchForm('mvz_dialog');
    this.commonModels(schema);
  }

  generateDmn() {
    this.fetchForm('generate_dmn_dialog');
    this.commonModels({
      GenerateDmnDialog: {
        data: {
          serviceId: get(this.card, 'id'),
        },
      },
    });
  }

  // todo common type for all cards
  commonModels(val: any) {
    this.$emit('commonModels', val);
  }

  get columns() {
    const headerStyle = 'font-size: 16px; font-weight: 600';
    return [
      {
        align: 'left',
        field: 'name',
        label: this.$t('ProcessesCard.name'),
        name: 'name',
        sortable: true,
        headerStyle,
      },
      {
        align: 'left',
        field: 'type',
        label: this.$t('ProcessesCard.type'),
        name: 'type',
        format: (val: Process) =>
          this.$te(`ProcessesCard.ProcessTypes.${val}`)
            ? this.$t(`ProcessesCard.ProcessTypes.${val}`)
            : val,
        sortable: false,
        style: 'white-space: pre-wrap',
        headerStyle,
      },
    ];
  }

  get columnsDMN() {
    const headerStyle = 'font-size: 16px; font-weight: 600';
    return [
      {
        align: 'left',
        field: 'name',
        label: this.$t('ProcessesCard.name'),
        name: 'name',
        sortable: true,
        headerStyle,
      },
      {
        align: 'left',
        field: 'id',
        label: this.$t('ProcessesCard.id'),
        name: 'id',
        sortable: false,
        style: 'white-space: pre-wrap',
        headerStyle,
      },
    ];
  }

  get columnsSurge() {
    const headerStyle = 'font-size: 16px; font-weight: 600';

    return [
      {
        align: 'left',
        field: 'interagency',
        label: this.$t('surge.table.cols.process'),
        name: 'interagency',
        sortable: true,
        headerStyle,
      },
      {
        align: 'left',
        field: 'parent',
        label: this.$t('surge.table.cols.interagency'),
        name: 'parent',
        sortable: false,
        style: 'white-space: pre-wrap',
        headerStyle,
      },
    ];
  }

  get loadingCard() {
    return (
      this.$store.getters['registryService/services/servicesLoading'] || false
    );
  }

  get card() {
    return cloneDeep(
      this.$store.getters['registryService/services/servicesCard']
    );
  }

  get goalColorMap() {
    return this.$store.getters['registryService/services/goalColorMap'];
  }

  get processes() {
    return get(this.card, 'processes', []);
  }

  get state() {
    return get(this.card, 'state', 'inProgress');
  }

  get DmnTables() {
    return get(this.card, 'tables', []);
  }

  get surgeTables() {
    return get<Surge[]>(this.card, 'interagencyWaves', []).map(v => ({
      ...v,
      uuid: v.uuid || v4()
    }));
  }

  get canEdit(): boolean {
    return this.$store.getters['registryService/services/canEdit'];
  }
}
</script>
