<template>
  <div>
    <Modal
      v-model="opened"
      scrollable
      :fullscreen="isFullscreen"
      :mask-closable="layout.maskClosable"
      :draggable="layout.draggable"
      :sticky="true"
      :reset-drag-position="true"
      :width="width"
    >
      <template #header>
        <div>
          <!--
            @slot 页头
          -->
          <slot name="header">
            <span class="title">{{ name }}</span>
            <span class="description">{{ description }}</span>
          </slot>
        </div>
      </template>
      <template #close>
        <div @click.stop>
          <Icon v-if="!isFullscreen" style="font-size: 20px; color: #999; position: relative; top: -3px" type="ios-expand" @click="isFullscreen = !isFullscreen" />
          <Icon v-if="isFullscreen" style="font-size: 20px; color: #999; position: relative; top: -3px" type="ios-contract" @click="isFullscreen = !isFullscreen" />
          <Icon type="ios-close" @click="opened = false" />
        </div>
      </template>
      <div class="ivu-ml-8 ivu-mr-8">
        <view-form v-if="!isCustom" ref="form" :readonly="readonly"></view-form>
        <component v-if="isCustom" ref="customComponent" :is="customComponent" :readonly="readonly" @on-ready="customComponentReady"></component>
      </div>
      <template #footer>
        <div>
          <Button v-for="(item, index) in outcomes" :key="index" type="primary" custom-icon="fa fa-check-circle" @click="action(item)">
            {{ item.name == null ? $t('Front_Btn_Agree') : item.name }}
          </Button>
          <Button type="warning" v-if="isRejectable" custom-icon="fa fa-reply" @click="reject()">{{ $t('Front_Btn_Reject') }}</Button>
          <Button type="primary" v-if="isBackable" custom-icon="fa fa-share" @click="back()">{{ $t('Front_Btn_Back_Previous') }}</Button>
          <Button type="primary" v-if="isRedirectable" custom-icon="fa fa-share" @click="$refs.redirectTaskForm.open()">{{ $t('Front_Btn_Redirect') }}</Button>
          <Button type="primary" v-if="isRecallable" custom-icon="fa fa-reply-all" @click="recall()">{{ $t('Front_Btn_Recall') }}</Button>
          <Button type="primary" v-if="isMessageEnable" custom-icon="fa fa-comment-dots" @click="openMessage()">{{ $t('Front_Btn_Leave_Message') }}</Button>
          <Button type="info" custom-icon="fa fa-route" @click="$refs.flowChart.open({ processInstID: task.processInstID })">{{ $t('Front_Btn_Process') }}</Button>
          <Button type="info" custom-icon="fa fa-history" @click="$refs.approvalHistoryTable.open({ processInstID: task.processInstID })">{{ $t('Front_Btn_History') }}</Button>
          <Button type="default" custom-icon="fa fa-times" @click="opened = false">{{ $t('Front_Btn_Close') }}</Button>
        </div>
      </template>
    </Modal>
    <modal-table ref="approvalHistoryTable" view-code="ApprovalHistoryModal"></modal-table>
    <modal-form ref="redirectTaskForm" view-code="RedirectTask">
      <template #footer>
        <Button type="primary" custom-icon="fa fa-check" @click="redirect()">{{ $t('Front_Btn_OK') }}</Button>
      </template>
    </modal-form>
    <Modal v-model="messageOpened" scrollable>
      <template #header>
        <div>
          <span class="title">{{ $t('Front_Label_Leave_Message') }}</span>
          <span class="description">{{ $t('Front_Label_Leave_Message_Desc') }}</span>
        </div>
      </template>
      <div class="ivu-ml-8 ivu-mr-8">
        <Form ref="messageForm" :model="messageData" label-position="top" label-colon="：" class="ivu-mt" @submit.prevent>
          <Row :gutter="24" type="flex">
            <Col v-bind="grid24">
              <FormItem
                :label="$t('Front_Label_Message_Content')"
                key="message"
                prop="message"
                :rules="{
                  required: true,
                  message: this.$t('Front_Msg_Please_Input'),
                  trigger: 'blur,change'
                }"
              >
                <Input type="textarea" :rows="6" v-model="messageData.message" />
              </FormItem>
            </Col>
          </Row>
        </Form>
      </div>
      <template #footer>
        <Button type="primary" custom-icon="fa fa-check" @click="submitMessage">{{ $t('Front_Btn_Submit') }}</Button>
        <Button type="default" custom-icon="fa fa-times" @click="messageOpened = false">{{ $t('Front_Btn_Close') }}</Button>
      </template>
    </Modal>
    <modal-form ref="rejectForm" view-code="RejectTask">
      <template #column="{ data, code }">
        <template v-if="code == 'rejectTo'">
          <Select v-model="$refs.rejectForm.data.rejectToID" :clearable="true" placeholder="退回发起人" :transfer="true">
            <Option v-for="item in rejectActivities" :key="item.id" :value="item.id">
              {{ item.name }}
            </Option>
          </Select>
        </template>
      </template>
      <template #footer>
        <Button type="primary" custom-icon="fa fa-check" @click="rejectSubmit()">{{ $t('Front_Btn_OK') }}</Button>
      </template>
    </modal-form>
    <flow-chart ref="flowChart" />
  </div>
</template>
<script>
  import { markRaw } from 'vue';
  import mixinPage from '../../mixins/page';
  import flowChart from '../../components/workflow/flow-chart.vue';
  import customModelApi from '../../api/customModel';
  import processInstApi from '../../api/processInst';
  import modelApi from '../../api/model';
  import taskApi from '../../api/task';

  export default {
    mixins: [mixinPage],
    components: { flowChart },
    data() {
      return {
        task: null,
        model: null,
        comment: null,
        outcomes: [],
        readonly: true,
        isRejectable: false,
        isBackable: false,
        isRedirectable: false,
        isMessageEnable: false,
        isRecallable: false,
        messageData: {
          message: null
        },
        messageOpened: false,
        opened: false,
        isCustom: false,
        width: 800,
        name: null,
        description: null,
        customComponent: null,
        form: null,
        isFullscreen: false,
        rejectActivities: []
      };
    },
    async created() {},
    computed: {},
    methods: {
      // 打开
      async open(row) {
        let applicationType = row.processInst.applicationType;
        this.outcomes = [];
        this.task = row;
        this.isRejectable = this.task.activityInst.activity.isRejectable && this.task.status == 'Pending';
        this.isBackable = this.task.activityInst.activity.isBackable && this.task.status == 'Pending';
        this.isRedirectable = this.task.activityInst.activity.isRedirectable && this.task.status == 'Pending';
        this.isMessageEnable = this.task.processInst.isMessageEnable && this.task.status == 'Pending';
        this.isRecallable = this.task.activityInst.activity.isRecallable && this.task.status == 'Finished' && !this.task.isCallbacked;
        this.isCustom = false;

        setTimeout(async () => {
          if (this.task.activityInst.activity.pageMode == 'Page') {
            // 路由跳转
            this.$router.push({ path: this.task.activityInst.activity.routerPath, query: { taskID: row.id } });
            return;
          } else if (this.task.activityInst.activity.pageMode == 'Component') {
            // 动态组件
            this.readonly = !this.task.activityInst.activity.isEditable || this.task.status != 'Pending';
            this.customComponent = markRaw(this.$pages[this.task.activityInst.activity.templateUrl]); // 动态组件
            this.isCustom = true;

            setTimeout(async () => {
              if (applicationType.isCustom) {
                this.model = await customModelApi.get(applicationType.model, row.processInst.modelID);
              } else {
                this.model = await modelApi.get(applicationType.model, row.processInst.modelID);
              }

              this.customComponentReady();

              this.opened = true;
            });
          } else if (this.task.activityInst.activity.pageMode == 'Form') {
            this.form = this.$refs.form;
            this.readonly = !this.task.activityInst.activity.isEditable || this.task.status != 'Pending';
            this.form.init(this.task.activityInst.activity.formViewCode, async view => {
              if (view.dataView.isCustom) {
                this.model = await customModelApi.get(applicationType.model, row.processInst.modelID);
              } else {
                this.model = await modelApi.get(applicationType.model, row.processInst.modelID);
              }

              this.width = this.form.formView.width || '800';
              this.name = this.form.formView.name;
              this.description = this.form.formView.description;
              this.form.data = this.model;

              setTimeout(async () => {
                this.form.onDataChange();
                this.form.clearValidate();
                this.opened = true;
              });
            });
          } else if (applicationType.pageMode == 'Page') {
            this.$router.push({ path: applicationType.routerPath, query: { taskID: row.id } });
            return;
          } else if (applicationType.pageMode == 'Component') {
            // 动态组件
            this.readonly = !this.task.activityInst.activity.isEditable || this.task.status != 'Pending';
            this.customComponent = markRaw(this.$pages[applicationType.templateUrl]); // 动态组件
            this.isCustom = true;

            setTimeout(async () => {
              if (applicationType.isCustom) {
                this.model = await customModelApi.get(applicationType.model, row.processInst.modelID);
              } else {
                this.model = await modelApi.get(applicationType.model, row.processInst.modelID);
              }

              this.customComponentReady();

              this.opened = true;
            });
          } else if (applicationType.pageMode == 'Form') {
            this.form = this.$refs.form;
            this.readonly = !this.task.activityInst.activity.isEditable || this.task.status != 'Pending';
            this.form.init(applicationType.formViewCode, async view => {
              if (view.dataView.isCustom) {
                this.model = await customModelApi.get(applicationType.model, row.processInst.modelID);
              } else {
                this.model = await modelApi.get(applicationType.model, row.processInst.modelID);
              }

              this.width = this.form.formView.width || '800';
              this.name = this.form.formView.name;
              this.description = this.form.formView.description;
              this.form.data = this.model;

              setTimeout(() => {
                this.form.onDataChange();
                this.form.clearValidate();
                this.opened = true;
              });
            });
          } else {
            this.error('Front_Msg_Setting_Error');
            return;
          }

          if (this.task.status == 'Pending') {
            let res = await modelApi.query('Outcome', { activityFromID: row.activityInst.activityID });
            this.outcomes = res.data;
          }
        });
      },
      // 自定义组件就绪
      customComponentReady() {
        if (this.$refs.customComponent.form) {
          this.form = this.$refs.customComponent.form;
          this.form.data = this.model;
          this.form.onDataChange();
          this.form.clearValidate();

          this.width = this.form.formView.width || '800';
          this.name = this.form.formView.name;
          this.description = this.form.formView.description;
        }
      },
      // 执行结果
      async action(outcome) {
        let isOK;

        if (outcome.ignoreValidation == true) {
          isOK = true;
        } else {
          if (this.isCustom && typeof this.$refs.customComponent.actionValidation === 'function') {
            isOK = await this.$refs.customComponent.actionValidation(outcome);

            if (!isOK) {
              return;
            }
          }

          isOK = await this.form.validate();
        }

        if (!isOK) {
          this.error('Front_Msg_Form_Validate_Fail');
        } else {
          this.confirmInput(
            'Front_Msg_Sure_To_Application' + '|' + (outcome.name == null ? this.$t('Front_Label_Agree') : outcome.name),
            this.$t('Front_Label_Comment'),
            async () => {
              let data = null;
              if (!this.readonly) {
                data = this.form.getFullData();

                if (!data) {
                  // 表格验证失败
                  return;
                }
              }

              if (this.isCustom && typeof this.$refs.customComponent.beforeAction === 'function') {
                await this.$refs.customComponent.beforeAction(outcome);
              }

              await taskApi.do(this.task.id, outcome.id, data, this.comment);
              this.success('Front_Msg_Success');
              this.resetNotice();
              this.$emit('on-after-action');
              this.opened = false;
            },
            comment => {
              this.comment = comment;
              return true;
            }
          );
        }
      },
      // 打开拒绝表单
      async reject() {
        if (this.isCustom && typeof this.$refs.customComponent.rejectValidation === 'function') {
          let isOK = await this.$refs.customComponent.rejectValidation();

          if (!isOK) {
            return;
          }
        }

        console.log('xxx', this.task.activityInst.activityID);

        let column = this.$refs.rejectForm.columns.find(item => item.code == 'rejectTo');

        if (column) {
          if (this.task.activityInst.activity.isRejectSelect == true) {
            this.rejectActivities = await taskApi.queryRejectTo(this.task.id);
            column.isShow = true;
          } else {
            column.isShow = false;
          }
        }

        this.$refs.rejectForm.open();
      },
      // 拒绝提交
      async rejectSubmit() {
        let isOK = await this.$refs.rejectForm.validate();

        if (!isOK) {
          this.error('Front_Msg_Form_Validate_Fail');
        } else {
          this.confirm('Front_Msg_Sure_To_Reject_Application', async () => {
            let model = this.$refs.rejectForm.data;

            await taskApi.reject(this.task.id, model.rejectToID, model.comment);
            this.success('Front_Msg_Success');
            this.resetNotice();
            this.$emit('on-after-action');
            this.$refs.rejectForm.data = {};
            this.$refs.rejectForm.close();
            this.opened = false;
          });
        }
      },
      // 撤回
      async recall() {
        this.confirmInput(
          'Front_Msg_Sure_To_Recall_Task',
          this.$t('Front_Label_Comment'),
          async () => {
            await taskApi.recall(this.task.id, this.comment);
            this.success('Front_Msg_Success');
            this.resetNotice();
            this.$emit('on-after-action');
            this.opened = false;
          },
          comment => {
            if (!(comment || '').trim()) {
              this.warning('Front_Msg_Please_Input_Recall_Reason');
              return false;
            } else {
              this.comment = comment;
              return true;
            }
          }
        );
      },
      // 退回上一步
      async back() {
        this.confirmInput(
          'Front_Msg_Sure_To_Back_Application',
          this.$t('Front_Label_Comment'),
          async () => {
            if (this.isCustom && typeof this.$refs.customComponent.beforeBack === 'function') {
              await this.$refs.customComponent.beforeBack(this.comment);
            }

            await taskApi.back(this.task.id, this.comment);
            this.success('Front_Msg_Success');
            this.resetNotice();
            this.$emit('on-after-action');
            this.opened = false;
          },
          comment => {
            if (!(comment || '').trim()) {
              this.warning('Front_Msg_Please_Input_Back_Reason');
              return false;
            } else {
              this.comment = comment;
              return true;
            }
          }
        );
      },
      // 转办
      async redirect() {
        let isOK = await this.$refs.redirectTaskForm.validate();

        if (!isOK) {
          this.error('Front_Msg_Form_Validate_Fail');
        } else {
          let model = this.$refs.redirectTaskForm.data;

          this.confirm('Front_Msg_Sure_To_Redirect_Application' + '|' + model.target.name, async () => {
            await taskApi.redirect(this.task.id, model.targetID, model.comment);
            this.success('Front_Msg_Success');
            this.resetNotice();
            this.$emit('on-after-action');
            this.$refs.redirectTaskForm.close();
            this.opened = false;
          });
        }
      },
      // 打开意见输入
      openMessage() {
        this.messageData.message = null;
        this.messageOpened = true;
      },
      // 提交意见
      async submitMessage() {
        let isOK = await this.$refs.messageForm.validate();

        if (!isOK) {
          this.error('Front_Msg_Form_Validate_Fail');
        } else {
          this.confirm('Front_Msg_Sure_To_Message_Application', async () => {
            await processInstApi.addMessage(this.task.processInstID, this.messageData.message);

            this.success('Front_Msg_Success', () => {
              this.messageData.message = null;
              this.messageOpened = false;
            });
          });
        }
      }
    }
  };
</script>
