<template>
  <div>
    <Modal
      v-model="opened"
      scrollable
      :mask-closable="maskClosable == null ? layout.maskClosable : maskClosable"
      :draggable="draggable == null ? layout.draggable : draggable"
      :sticky="true"
      :reset-drag-position="true"
      :width="formView.width || '800'"
      :before-close="beforeClose"
      @on-visible-change="onVisibleChange"
    >
      <div slot="header">
        <!--
            @slot 页头
        -->
        <slot name="header">
          <span class="title">{{ getNameI18n(formView) }}</span>
          <span class="description">{{ getDescI18n(formView) }}</span>
        </slot>
      </div>
      <div class="ivu-ml-8 ivu-mr-8">
        <view-form ref="form" :view-code="viewCode" :readonly="!canSave()" :defaultData="defaultData" :setting-enable="settingEnable" @on-change="onChange" @on-ready="onReady">
          <template slot-scope="{ form }" slot="top">
            <!--
                @slot 顶部
                @binding {object} form 表单对象
            -->
            <slot name="top" :form="form"></slot>
          </template>
          <template slot-scope="{ form, data, column, code }" slot="column">
            <!--
                @slot 自定义列
                @binding {object} form 表单对象
                @binding {object} data 数据对象
                @binding {object} column 列对象
                @binding {string} code 列代码
            -->
            <slot name="column" :form="form" :data="data" :column="column" :code="code"></slot>
          </template>
          <template slot-scope="scope" slot="tableColumn">
            <!--
                @slot 内嵌表格自定义列
                @binding {object} table 表格对象
                @binding {object} tableColumn 表格列对象
                @binding {string} tableCode 表格列代码
                @binding {object} row 行对象
                @binding {int} index 行序号
                @binding {object} column 行对象
                @binding {string} code 列代码
            -->
            <slot
              name="tableColumn"
              :table="scope.table"
              :tableColumn="scope.tableColumn"
              :tableCode="scope.tableCode"
              :row="scope.row"
              :index="scope.index"
              :column="scope.column"
              :code="scope.code"
            ></slot>
          </template>
          <template slot-scope="scope" slot="tableCommand">
            <!--
                @slot 内嵌表格工具栏
                @binding {object} table 表格对象
                @binding {object} tableColumn 表格列对象
                @binding {string} tableCode 表格列代码
                @binding {object} row 行对象
                @binding {int} index 行序号
            -->
            <slot name="tableCommand" :table="scope.table" :tableColumn="scope.tableColumn" :tableCode="scope.tableCode" :row="scope.row" :index="scope.index"></slot>
          </template>
          <template slot-scope="{ form }" slot="bottom">
            <!--
                @slot 底部
                @binding {object} form 表单对象
            -->
            <slot name="bottom" :form="form"></slot>
          </template>
        </view-form>
      </div>
      <div slot="footer">
        <!--
            @slot 页脚
        -->
        <slot name="footer">
          <Button type="primary" custom-icon="fa fa-save" v-if="canSave() && saveEnable" @click="onSave">{{ $t('Front_Btn_Save') }}</Button>
        </slot>
        <Button type="default" custom-icon="fa fa-times" @click="clickClose">{{ $t('Front_Btn_Close') }}</Button>
        <Button type="error" :title="$t('Front_Btn_Setting')" custom-icon="fa fa-cog" v-if="settingEnable && allow('permission/formView')" @click="settingOpen"></Button>
      </div>
    </Modal>
    <form-setting ref="setting" v-if="settingActive" :is-setting="true" @layout-mode="layoutMode" @on-change="init" />
    <form-setting-layout ref="settingLayout" v-if="settingActive" :is-setting="true" @list-mode="listMode" @on-change="init" />
  </div>
</template>
<script>
  import mixinPage from '../../mixins/page';
  import modelApi from '../../api/model';
  import customModelApi from '../../api/customModel';
  import formSetting from './form-setting';
  import formSettingLayout from './form-setting-layout';

  /**
   * @displayName modal-form 表单对话框
   */
  export default {
    mixins: [mixinPage],
    components: { formSetting, formSettingLayout },
    data() {
      return {
        opened: false,
        formView: {},
        settingActive: false
      };
    },
    async created() {},
    props: {
      /**
       * 表单视图代码
       */
      viewCode: {
        type: String
      },
      /**
       * 只读
       */
      readonly: {
        type: Boolean,
        default: false
      },
      /**
       * 预设默认值
       */
      defaultData: {
        type: Object,
        default() {
          return {};
        }
      },
      /**
       * 允许创建
       */
      createEnable: {
        type: Boolean,
        default: true
      },
      /**
       * 允许编辑
       */
      editEnable: {
        type: Boolean,
        default: true
      },
      /**
       * 是否允许保存
       */
      saveEnable: {
        type: Boolean,
        default: true
      },
      /**
       * 是否允许点击遮罩层关闭
       */
      maskClosable: {
        type: Boolean,
        default: null
      },
      /**
       * 是否允许拖动
       */
      draggable: {
        type: Boolean,
        default: null
      },
      /**
       * 是否允许配置界面
       */
      settingEnable: {
        type: Boolean,
        default: true
      },
      /**
       * 验证方法
       */
      validateFunction: {
        type: Function
      },
      /**
       * 关闭前方法
       */
      beforeClose: {
        type: Function
      }
    },
    computed: {
      // formView () {
      //     return this.$refs.form.formView;
      // },
      data() {
        return this.$refs.form.data;
      },
      columns() {
        return this.$refs.form.columns;
      }
    },
    methods: {
      /**
       * 初始化
       *
       * @param {string} viewCode 视图代码
       * @param {function} callback 完成后回调方法
       * @param {function} onFail 失败后回调方法
       * @public
       */
      async init(viewCode, callback, onFail) {
        await this.$refs.form.init(viewCode, callback, onFail);
      },
      /**
       * 加载视图
       *
       * @param {object} view 视图
       * @public
       */
      loadView(view) {
        this.$refs.form.loadView(view);
      },
      /**
       * 打开
       *
       * @param {object} data 数据
       * @param {object} compare 对比数据，不一致标红
       * @public
       */
      open(data, compare) {
        if (data) {
          this.$refs.form.data = this.copy(data);
          this.$refs.form.compareData = compare;
          // this.$refs.form.reset();
        } else {
          this.$refs.form.setDefault();
        }

        setTimeout(() => {
          this.$refs.form.onDataChange();
          this.$refs.form.clearValidate();
          this.opened = true;
        });
      },
      /**
       * 用默认值打开
       *
       * @param {object} def 默认值
       * @public
       */
      openDefault(def) {
        this.$refs.form.setDefault(def);

        setTimeout(() => {
          this.$refs.form.onDataChange();
          this.$refs.form.clearValidate();
          this.opened = true;
        });
      },
      /**
       * 设置数据
       *
       * @param {object} data 数据
       * @public
       */
      setData(data) {
        this.$refs.form.data = data;
        //this.forceUpdate();
      },
      /**
       * 关闭
       *
       * @public
       */
      async close() {
        this.opened = false;
      },
      /**
       * 设为默认值
       *
       * @param {object}} data 默认值
       * @public
       */
      setDefault(data) {
        this.$refs.form.setDefault(data);
      },
      /**
       * 验证
       *
       * @public
       */
      validate() {
        return this.$refs.form.validate();
      },
      /**
       * 获取完整数据
       *
       * @public
       */
      getFullData() {
        return this.$refs.form.getFullData();
      },
      /**
       * 强制更新
       *
       * @public
       */
      forceUpdate() {
        this.$refs.form.$forceUpdate();
      },
      onChange(sender, oldValue, newValue, selected) {
        /**
         * 数据变化事件
         * @property {object} sender 触发的列对象
         * @property {object} oldValue 原数据
         * @property {object} newValue 新数据
         * @property {object} selected 选中对象（弹出选择框等有效）
         */
        this.$emit('on-change', sender, oldValue, newValue, selected);
      },
      /**
       * 设置表格字段内容
       *
       * @param {string} code 字段
       * @param {object} value 值
       * @public
       */
      setTableData(code, value) {
        this.$refs.form.setTableData(code, value);
      },
      /**
       * 刷新
       *
       * @public
       */
      refresh() {
        this.$refs.form.refresh();
      },
      onReady(formView) {
        this.formView = formView;
      },
      onVisibleChange(show) {
        // 关闭时清空数据
        if (!show) {
          this.$refs.form.reset();
          /**
           * 关闭事件
           */
          this.$emit('on-close');
        }
      },
      canSave() {
        if (this.readonly) {
          return false;
        }

        if (this.$refs.form && this.$refs.form.data) {
          if (!this.$refs.form.data.id) {
            return this.createEnable;
          } else {
            return this.editEnable;
          }
        } else {
          return true;
        }
      },
      // 保存
      async onSave() {
        let isOK = await this.$refs.form.validate();

        if (!isOK) {
          this.error('Front_Msg_Form_Validate_Fail');
        } else {
          // 验证方法
          if (this.validateFunction) {
            if (!this.validateFunction()) {
              return;
            }
          }

          /**
           * 保存前事件
           */
          this.$emit('on-before-save');

          let data = this.$refs.form.getFullData();
          if (!data) {
            // 表格验证失败
            return;
          }

          this.confirm('Front_Msg_Sure_To_Save', async () => {
            if (this.formView.isCustom) {
              if (!data.id) {
                await customModelApi.add(this.formView.model, data);
              } else {
                await customModelApi.update(this.formView.model, data);
              }
            } else {
              if (!data.id) {
                await modelApi.add(this.formView.model, data);
              } else {
                await modelApi.update(this.formView.model, data);
              }
            }

            this.success('Front_Msg_Success', () => {
              this.$refs.form.data = {};
              /**
               * 保存后事件
               */
              this.$emit('on-after-save', data);
              this.close();
            });
          });
        }
      },
      // 打开设置界面
      settingOpen() {
        this.settingActive = true;

        setTimeout(async () => {
          this.$refs.settingLayout.open(this.formView, this.copy(this.formView.columns));
        });
      },
      // 切换至列表模式
      listMode({ dataView, columns }) {
        this.$refs.settingLayout.close();
        this.$refs.setting.open(dataView, columns);
      },
      // 切换至预览模式
      layoutMode({ dataView, columns }) {
        this.$refs.setting.close();
        this.$refs.settingLayout.open(dataView, columns);
      },
      // 点击关闭按钮
      clickClose() {
        if (typeof this.beforeClose == 'function') {
          this.beforeClose().then(
            () => {
              this.close();
            },
            () => {}
          );
        } else {
          this.close();
        }
      },
      // 获取多语言名称
      getNameI18n(formView) {
        if (this.layout.showI18n) {
          if (formView.code) {
            let key = 'DataView_' + formView.code;
            let text = this.$t(key);
            if (text == key) {
              return formView.name;
            } else {
              return text;
            }
          }
        } else {
          return formView.name;
        }
      },
      // 获取多语言描述
      getDescI18n(formView) {
        if (this.layout.showI18n) {
          if (formView.code) {
            let key = 'DataView_' + formView.code + '_$Desc';
            let text = this.$t(key);
            if (text == key) {
              return formView.name;
            } else {
              return text;
            }
          }
        } else {
          return formView.description;
        }
      }
    }
  };
</script>
