<template>
  <div
    :class="_wrapClass"
    v-show="visible"
    v-if="realVisible || !destroy"
  >
    <template v-if="withMask">
      <transition
        name="hive-fade-in"
        appear
      >
        <div
          v-show="visible"
          ref="mask"
          :class="_maskClass"
          @click="onMaskClick"
        />
      </transition>
    </template>
    <transition
      name="hive-flow-in"
      appear
    >
      <!-- 必须是在子元素上添加v-if / v-show <transition>才有效 -->
      <div
        v-show="visible"
        :class="_getClassNames"
        :style="width ? 'width:'+ width +'px;min-width:auto;':''"
      >
        <div
          :class="_headerClass"
          v-if="title"
        >
          <div :class="_titleClass">
            <Icon
              v-if="type"
              :class="_iconClass"
              :icon="_iconType"
            />
            {{ title }}
            <Icon
              @click="onCloseClick"
              :class="_closeClass"
              icon="clear"
            />
          </div>
        </div>
        <div :class="_contentClass">
          <!-- @slot content 内容 -->
          <slot>
            <template v-if="typeof content === 'string'">
              {{ content }}
            </template>
            <template v-if="content && typeof content === 'function'">
              <RenderCell :render="content" />
            </template>
          </slot>
        </div>
        <div :class="_footerClass">
          <!-- @slot footer 内容 -->
          <slot name="footer">
            <Button
              :class="_confirmClass"
              type="primary"
              @click="onConfirmClick"
            >
              {{ confirmText }}
            </Button>
            <Button
              v-if="!cancelHidden"
              :class="_cancelClass"
              @click="onCancelClick"
            >
              {{ cancelText }}
            </Button>
          </slot>
        </div>
      </div>
    </transition>
  </div>
</template>

<script>
import Emitter from 'utils-lib/dist/emitter';
import Button from '../button';
import Icon from '../icon';
import RenderCell from '../render-cell';

const name = 'hive-modal';

export default {
  name,
  components: {
    Button,
    Icon,
    RenderCell
  },
  mixins: [Emitter],
  props: {
    /**
     * 是否显示Modal
     */
    value: Boolean,
    /**
     * 标题
     */
    title: String,
    /**
     * 对话框宽度
     */
    width: [String, Number],
    /**
     * 类型 可选 success | error | warning | info
     */
    type: String,
    /**
     * modal 内容，默认渲染 modal 的 default slot
     */
    content: {
      type: [String, Function]
    },
    /**
     * 确认按钮文字
     */
    confirmText: {
      type: String,
      default: '确认'
    },
    /**
     * 取消按钮文字
     */
    cancelText: {
      type: String,
      default: '取消'
    },
    /**
     * 自定义icon
     * @member icon图标列表
     */
    iconType: String,
    /**
     * 是否隐藏取消按钮
     */
    cancelHidden: {
      type: Boolean,
      default: false
    },
    /**
     * 是否显示遮罩层
     */
    withMask: {
      type: Boolean,
      default: true
    },
    /**
     * 点击遮罩层是否关闭modal
     */
    maskClosable: {
      type: Boolean,
      default: true
    },
    /**
     * 关闭modal是否销毁
     */
    destroy: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      visible: this.value,
      realVisible: this.value,
      titleIcon: 'circle_tick',
      masckActive: false
    };
  },
  computed: {
    _getClassNames() {
      return [name];
    },
    _wrapClass() {
      return [`${name}-wrap`];
    },
    _maskClass() {
      return [`${name}-mask`];
    },
    _headerClass() {
      return [`${name}-header`];
    },
    _titleClass() {
      return [
        `${name}-title`,
        {
          [`${name}-title--icon`]:
            this.type === 'success' ||
            this.type === 'error' ||
            this.type === 'warning' ||
            this.type === 'info'
        }
      ];
    },
    _contentClass() {
      return [`${name}-content`];
    },
    _footerClass() {
      return [`${name}-footer`];
    },
    _closeClass() {
      return [`${name}__close`];
    },
    _cancelClass() {
      return [`${name}__cancel`];
    },
    _confirmClass() {
      return [`${name}__confirm`];
    },
    _iconClass() {
      return [
        {
          [`${name}-icon`]: this.type,
          [`${name}-icon--${this.type}`]: this.type
        }
      ];
    },
    _iconType() {
      if (this.iconType) {
        return this.iconType;
      }
      switch (this.type) {
        case 'error':
          return 'circle_clear';
        case 'warning':
          return 'circle_error';
        case 'info':
          return 'circle_info';
        case 'success':
          return 'circle_tick';
        default:
          return '';
      }
    }
  },
  watch: {
    value(value) {
      // visiblechange事件
      if (this.$slots.footer && !value && !this.masckActive) {
        this.setVisible(false);
      }
      value && this.setVisible(value);
    }
  },
  mounted() {
    this.aniT = 0;
    if (this.visible) {
      document.body.appendChild(this.$el);
    }
  },
  destroyed() {
    try {
      this.$el && document.body.removeChild(this.$el);
    } catch (e) {}
  },
  methods: {
    getBrowserScrollSize() {
      let calcSize;

      const innerBox = document.createElement('div');

      innerBox.style.width = '100%';
      innerBox.style.height = '200px';

      const testBox = document.createElement('div');

      testBox.style.position = 'absolute';
      testBox.style.top = 0;
      testBox.style.left = 0;
      testBox.style.pointerEvents = 'none';
      testBox.style.visibility = 'hidden';
      testBox.style.width = '200px';
      testBox.style.height = '150px';
      testBox.style.overflow = 'hidden';

      testBox.appendChild(innerBox);

      document.body.appendChild(testBox);

      const widthContaine = innerBox.offsetWidth;
      testBox.style.overflow = 'scroll';
      let widthScroll = innerBox.offsetWidth;

      if (widthContaine === widthScroll) {
        widthScroll = testBox.clientWidth;
      }

      document.body.removeChild(testBox);

      calcSize = widthContaine - widthScroll;

      return calcSize;
    },
    setBodyCalcSize(clear) {
      const bodyIsScroll =
        document.body.scrollHeight >
          (window.innerHeight || document.documentElement.clientHeight) &&
        window.innerWidth > document.body.offsetWidth;
      if (!bodyIsScroll) {
        return;
      }
      if (clear) {
        document.body.style.position = '';
        document.body.style.width = '';
        return;
      }
      const calcSize = this.getBrowserScrollSize();

      if (calcSize) {
        document.body.style.position = 'relative';
        document.body.style.width = `calc(100% - ${calcSize}px)`;
      }
    },
    onConfirmClick() {
      this.setVisible(false);
      /**
       * 点击确认回调函数
       */
      this.$emit('confirm');
    },
    onCancelClick() {
      this.setVisible(false);
    },
    onCloseClick() {
      this.setVisible(false);
    },
    onMaskClick(e) {
      this.masckActive = true;
      this.maskClosable && this.setVisible(false);
    },
    setVisible(value) {
      if (!value) {
        /**
         * 关闭回调函数
         */
        this.$emit('close');
        this.visible = value;
        clearTimeout(this.aniT);
        this.aniT = setTimeout(() => {
          document.body.style.overflow = '';
          this.setBodyCalcSize(true);
          if (this.$el && this.$el.parentNode && this.destroy) {
            this.$el.parentNode.removeChild(this.$el);
          }
          /**
           * 关闭动画结束回调函数
           */
          this.$emit('closed');
          this.realVisible = false;
        }, 300);
      } else {
        this.visible = value;
        this.realVisible = value;
        document.body.appendChild(this.$el);
        this.setBodyCalcSize();
        document.body.style.overflow = 'hidden';
        /**
         * 显示回调函数
         */
        this.$emit('open');
        clearTimeout(this.aniT);
        this.aniT = setTimeout(() => {
          /**
           * 显示动画结束回调函数
           */
          this.$emit('opened');
        }, 300);
      }
      /**
       * 状态改变回调函数
       */
      this.$emit('input', value);
    },
    afterClose() {
      this.realVisible = false;
    }
  }
};
</script>
