<style lang="scss" scoped>
.modal {
  position: fixed;
  left: 0;
  top: 0;
  bottom: 0;
  right: 0;
  width: 100%;
  height: 100%;
  display: block;
  z-index: 999;
  text-align: center;

  &:before {
    content: '';
    display: inline-block;
    height: 100%;
    vertical-align: middle;
  }
}

.modal-dialog {
  position: relative;
  // margin: 0 auto;
  display: inline-block;
  max-width: 100%;
  vertical-align: middle;
  // text-align: left;
}

.modal-top {
  /* display: table-cell;
    vertical-align: top;
    text-align: center; */
  display: flex;
  justify-content: center;
  align-items: flex-start;

  &:before {
    vertical-align: top;
  }
  .modal-dialog {
    vertical-align: top;
  }
}

.modal-bottom {
  /* display: table-cell;
    vertical-align: bottom;
    text-align: center; */
  display: flex;
  justify-content: center;
  align-items: flex-end;

  &:before {
    vertical-align: bottom;
  }
  .modal-dialog {
    vertical-align: bottom;
  }
}

.modal-flex,
.modal-center {
  display: flex;
  justify-content: center;
  align-items: center;
}

.mask {
  width: 100%;
  height: 100%;
  display: block;
  background: rgba(0, 0, 0, 0.6);
  position: absolute;
  left: 0;
  top: 0;
}

.modal-trans {
  pointer-events: none;
  .modal-dialog {
    pointer-events: visible;
  }
}

.modal-enter-active,
.modal-leave-active {
  transition: all 0.25s;
  .modal-dialog {
    transition: transform 0.25s ease-out;
  }
  &.modal-large {
    transition: all 0.25s;
    .modal-dialog {
      transition: transform 0.25s ease-in-out;
    }
  }
}

.modal-enter,
.modal-leave-active {
  opacity: 0;
  &.modal-up {
    .modal-dialog {
      transform: translateY(30%);
    }
    &.modal-large {
      .modal-dialog {
        transform: translateY(100%);
      }
    }
  }
  &.modal-down {
    .modal-dialog {
      transform: translateY(-30%);
    }
    &.modal-large {
      .modal-dialog {
        transform: translateY(-100%);
      }
    }
  }
  &.modal-scale {
    .modal-dialog {
      transform: scale(0.8);
    }
    &.modal-large {
      .modal-dialog {
        transform: scale(0.5);
      }
    }
  }
}
</style>

<template>
  <transition name="modal" :appear="true" @before-enter="beforeEnter" @after-enter="afterEnter" @before-leave="beforeLeave" @after-leave="afterLeave">
    <div v-if="seen" :class="classes" :style="modalStyles">
      <div v-if="mask" class="mask" @click.self.prevent.stop="maskhit" :style="maskStyle"></div>
      <div ref="modal" class="modal-dialog" :style="style">
        <slot></slot>
      </div>
    </div>
  </transition>
</template>

<script>
export default {
  name: 'Modal',
  props: {
    transition: {
      type: String,
      default: 'up', // [fade, scale, ]
    },
    position: {
      type: String,
      default: 'flex', // [top, center, bottom]
    },
    large: {
      type: Boolean,
      default: false,
    },
    flex: {
      type: Boolean,
      default: false,
    },
    styles: {
      type: Object,
      default: null,
    },
    modalStyles: {
      type: Object,
      default: null,
    },
    visible: {
      type: Boolean,
      default: false,
    },
    closeable: {
      type: Boolean,
      default: true,
    },
    global: {
      type: Boolean,
      default: false,
    },
    mask: {
      type: Boolean,
      default: true,
    },
    opacity: {
      type: Number,
      default: 0.6,
    },
    transparent: {
      type: Boolean,
      default: false,
    },
    single: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      destroyed: false,
      seen: this.visible,
    }
  },
  provide() {
    const { ok: modalOk, cancel: modalCancel, close: modalClose } = this;
    return {
      modalOk,
      modalCancel,
      modalClose,
    }
  },
  computed: {
    classes() {
      return ['modal', this.large ? 'modal-large' : '', this.flex ? 'modal-flex' : `modal-${this.position}`, this.transition ? `modal-${this.transition}` : '', this.transparent ? 'modal-trans' : '']
    },
    style() {
      // let defaultStyle = this.flex ? {} : {top: '10%'};
      let defaultStyle = {}
      Object.assign(defaultStyle, this.styles)
      return defaultStyle
    },
    maskStyle() {
      return {
        background: `rgba(0,0,0,${this.opacity})`,
      }
    },
  },
  watch: {},
  created() {
    this.target = this.global && this.$parent.target ? this.$parent.target : document.body
    // this.$root.$el.appendChild(this.$el);
    !this.global &&
      this.$nextTick(() => {
        // document.body.appendChild(this.$el);
        this.target.append(this.$el)
      })
  },
  mounted() {},
  beforeDestroy() {},
  destroyed() {
    // console.log('child destroyed');
    // document.body.removeChild(this.$el);
    this.target.removeChild(this.$el)
  },
  methods: {
    open() {
      if (!this.seen) {
        this.seen = true
      }
    },
    close() {
      if (this.seen) {
        this.seen = false
      }
    },
    ok(data) {
      this.close()
      this.$emit('ok', data)
    },
    cancel(data) {
      this.close()
      this.$emit('cancel', data)
    },
    maskhit() {
      if (this.closeable) {
        this.cancel()
      }
    },
    beforeEnter() {
      this.$emit('open')
    },
    afterEnter() {
      this.$emit('opened')
    },
    beforeLeave() {
      this.$emit('close')
    },
    afterLeave() {
      this.$emit('closed')
      if (!this.single && this.global) {
        this.$destroy()
        this.$parent.remove()
      }
    },
  },
}
</script>
