<template>
  <el-dialog
    ref="dialog"
    v-dialogDrag
    :class="{ dialog: true, 'no-gutter': !gutter }"
    :visible.sync="dialogVisible"
    v-bind="{ appendToBody: true, width: '368px', ...$attrs }"
    @closed="onClosed"
    @open="onOpen"
    @opened="onOpened"
    v-on="listeners"
    :style="`--max-height: ${maxHeight.includes('calc') ? maxHeight : `calc(${maxHeight} - 54px)`}`"
  >
    <slot name="title">
      <div slot="title">
        <span class="title">{{ title }}</span>
      </div>
    </slot>
    <slot />
    <slot name="footer">
      <span slot="footer" v-if="footer">
        <el-button type="primary" size="small" @click="onSubmit" :loading="loading" :disabled="disabled || submitted">
          提 交
        </el-button>
        <el-button size="small" @click="onCancel">取 消</el-button>
      </span>
    </slot>
  </el-dialog>
</template>

<script lang="ts">
  import { ElDialog } from 'element-ui/types/dialog'
  import { ElForm } from 'element-ui/types/form'
  import { Vue, Component, Prop, PropSync } from 'vue-property-decorator'

  @Component({ name: 'TfDialog', inheritAttrs: false })
  export default class TfDialog extends Vue {
    @PropSync('visible', { type: Boolean, default: false }) dialogVisible!: boolean
    @Prop({ type: String }) title!: string
    @Prop({ type: Boolean }) disabled!: boolean
    @Prop({ type: Boolean, default: false }) loading!: boolean
    @Prop({ type: Boolean, default: true }) clear!: boolean
    @Prop({ type: Boolean, default: true }) footer!: boolean
    @Prop({ type: Boolean, default: true }) gutter!: boolean
    @Prop({ type: String, default: 'calc(90vh - 54px)' }) maxHeight!: string

    timer: number = null
    submitted: boolean = false

    $refs!: { dialog: ElDialog }

    get listeners() {
      const { open, opened, closed, submit, ...rest } = this.$listeners
      return rest
    }

    onOpen() {
      try {
        if (this.clear) {
          const { clearValidate } = (this.$parent.$refs['form'] as ElForm) || {}
          setTimeout(() => {
            clearValidate && clearValidate()
          }, 0)
        }
      } catch (error) {
        console.log(error)
      }

      this.$emit('open')
    }

    onOpened() {
      try {
        setTimeout(() => {
          ;(this.$slots.default || []).forEach(({ componentInstance }) => {
            const { clearValidate } = (componentInstance as any) || {}
            if (clearValidate) {
              clearValidate()
            }
          })
        }, 0)
      } catch (error) {
        console.log(error)
      }
      this.$emit('opened')
    }

    onClosed() {
      try {
        if (this.clear) {
          Object.keys(this.$parent.$refs)
            .filter((key) => String(key).startsWith('form'))
            .forEach((key) => {
              const { resetFields } = (this.$parent.$refs[key] as ElForm) || {}
              resetFields && resetFields()
            })
        }
      } catch (error) {
        console.log(error)
      }

      try {
        if (this.clear) {
          ;(this.$slots.default || []).forEach(({ componentInstance }) => {
            const { resetFields } = (componentInstance as any) || {}
            if (resetFields) {
              resetFields()
            }
          })
        }
      } catch (error) {
        console.log(error)
      }
      this.$emit('closed')
      this.submitted = false

      try {
        // 重置拖到过的dialog位置
        const dialogDom = this.$refs.dialog.$el.querySelector('.el-dialog') as HTMLElement
        if (dialogDom) {
          dialogDom.style.removeProperty('left')
          dialogDom.style.removeProperty('top')
        }
      } catch (error) {
        console.log(error)
      }
    }

    onSubmit() {
      if (!this.timer) {
        this.$emit('submit')
        this.submitted = true
        setTimeout(() => {
          this.submitted = false
        }, 1000)
      } else {
        clearTimeout(this.timer)
        this.timer = window.setTimeout(() => {
          this.timer = null
        }, 1000)
      }
    }

    onCancel() {
      this.dialogVisible = false
      this.$emit('cancel')
    }

    updated() {
      this.$nextTick(() => {
        /**我也不知道为什么title会被传到html上 */
        ;[...document.querySelectorAll('.dialog')].forEach((dialog) => {
          dialog.removeAttribute('title')
        })
      })
    }
  }
</script>
<style lang="scss" scoped>
  .dialog {
    font-size: $--font-size-base;
    $radius: $--border-radius-base;
    $font-color: $--color-white;
    $bg-color: $--color-primary;
    --max-height: calc(85vh - 54px);
    border-radius: $radius;
    display: flex;
    justify-content: center;
    align-items: center;
    >>> .el-dialog {
      background-color: transparent;
      max-width: 85vw;
      margin-top: 0 !important;

      &__header {
        background-color: $bg-color;
        color: $font-color;
        border-bottom-color: $bg-color;
        text-indent: 0;
        padding: $gutter + 1px;
        display: flex;
        align-items: center;
        justify-content: space-between;
        border-top-left-radius: $radius;
        border-top-right-radius: $radius;
        .title {
          font-size: $--font-size-medium;
          color: $font-color;
          font-weight: 500;
        }
        &btn {
          position: relative;
          top: 0;
          right: 0;
          i.el-icon-close {
            color: $font-color !important;
            font-size: 1.2em;
          }
        }
      }
      &__body {
        background-color: #fff;
      }
      &__footer {
        background-color: #fff;
        border-bottom-left-radius: $radius;
        border-bottom-right-radius: $radius;
      }
      .el-dialog__body {
        padding: $gutter-medium;
        max-height: var(--max-height);
        overflow: hidden auto;
        @include base-scroll-bar();
      }
    }
    &.no-gutter {
      >>> .el-dialog {
        .el-dialog__body {
          padding: 0;
        }
      }
    }
  }
</style>
