<template>
  <Transition name="cy-dialog">
    <div class="cy-dialog"
         @animationend="animationEnd"
         @keydown.esc="closed"
         ref="dialogRef"
         :style="fullScreen ? fullScreenStyle : dislogStyle"
         v-show="modelValue"
         :class="fullScreen ? 'cy-dialog__fullScreen' : 'cy-dialog__cancelFullScreen' ">
      <div class="cy-dialog__header" ref="dialogHeadRef"
           @mousedown.stop.prevent>
        <div class="cy-dialog__img">
          <img :src="iconImg === null ? genTextPortrait(title.slice(0, 1)) : iconImg" alt="">
        </div>
        <div class="cy-dialog__title">
          {{ title }}
        </div>
        <div class="cy-dialog__icon">
          <div style="background-color: rgb(253,201,45)">
            <i class="iconfont icon-suoxiao"/>
          </div>
          <div style="background-color: rgb(40,211,63)" @click="clickFullScreen">
            <i class="iconfont"
               :class="fullScreen ? 'icon-quxiaoquanping' : 'icon-quanping' ">
            </i>
          </div>
          <div class="cy-dialog__close" @click="closed" style="background-color: rgb(254,98,84)">
            <i class="iconfont icon-guanbi"></i>
          </div>
        </div>
      </div>
      <div class="cy-dialog__main">
        <slot/>
      </div>
    </div>
  </Transition>
</template>

<script setup name='XcDialog' lang="ts">
import {Ref, ref, watch, onMounted, nextTick} from "vue";
import {useDraggable} from '@vueuse/core'
import {$ref} from "vue/macros";
import {genTextPortrait} from '@/utils/portrait'

interface dialogConfig {
  fullScreen: boolean,
  title: string,
  top?: number,
  dialog: boolean,
  img?: any,
  width: '',
}

const props = defineProps({
  title: {
    type: String,
    default: '对话框',
  },
  fullScreen: {
    type: Boolean,
    default: false
  },
  top: {
    type: Number,
    default: 20
  },
  zoom: {
    type: Boolean,
    default: true
  },
  drag: {
    type: Boolean,
    default: true
  },
  iconImg: {
    type: [Object, String],
    default: null
  },
  width: {
    type: [String],
    default: '30%',
  },
  modelValue: {
    type: Boolean,
    default: false
  },
  x: {
    type: Number,
    default: null
  },
  y: {
    type: Number,
    default: null
  }
})
const emit = defineEmits(['closed', 'update:modelValue'])
const dialogRef: Ref<HTMLElement | null> = ref(null)
const dialogHeadRef: Ref<HTMLElement | null> = ref(null)

const draggable = ref()
const fullScreenStyle = $ref({
  position: 'fixed',
  top: '0',
  left: '0',
  width: '100%',
  height: '100%',
  zIndex: 0,
})

let dislogStyle = $ref({
  left: '',
  top: '',
  zIndex: 0,
  width: props.width
})

let fullScreen = $ref(props.fullScreen)

const clickFullScreen = () => {
  if (props.zoom) {
    fullScreen = !fullScreen
  }
  setUpzIndex()
}

const setUpzIndex = () => {
  let zIndex = [...document.all].reduce((r, e) => Math.max(r, +window.getComputedStyle(e).zIndex || 0), 0)
  fullScreenStyle.zIndex = zIndex
  dislogStyle.zIndex = zIndex
}

const closed = async () => {
  emit('update:modelValue', false)
}

const animationEnd = (val) => {
  if (!props.modelValue) {
    emit('closed')
  }
}

watch(() => draggable.value?.x, async () => {
  if (props.fullScreen) return
  let right = window.innerWidth - dialogRef.value!.clientWidth
  if (draggable.value.x < 0) {
    draggable.value.x = 0
  } else if (draggable.value.x > right) {
    draggable.value.x = right
  }
  dislogStyle.left = draggable.value.x + 'px'
})

watch(() => draggable.value?.y, async () => {
  if (props.fullScreen) return
  let bottom = window.innerHeight - dialogRef.value!.clientHeight
  if (draggable.value.y < 0) {
    draggable.value.y = 0
  } else if (draggable.value.y > bottom) {
    draggable.value.y = bottom
  }
  dislogStyle.top = draggable.value.y + 'px'
})

const calculationDisplayPosition = () => {
  if (props.x === null || props.y === null) {
    let top = (window.innerHeight * (props.top / 100))
    let left = (window.innerWidth / 2) - (getDialogWidth() / 2);
    draggable.value = useDraggable(dialogHeadRef, {
      initialValue: {x: left as number, y: top as number},
    });
  } else {
    draggable.value = useDraggable(dialogHeadRef, {
      initialValue: {x: props.x, y: props.y},
    });
  }
}

const getDialogWidth = () => {
  let dialogRefWidth = dialogRef.value?.clientWidth
  if (dialogRefWidth !== null && dialogRefWidth > 0) {
    return <Number>dialogRefWidth
  }
  if (typeof props.width === 'string') {
    if (props.width.includes('%')) {
      let w = parseInt(props.width) / 100
      return window.innerWidth * w
    } else if (props.width.includes('px')) {
      return parseInt(props.width)
    }
  } else {
    return <Number>props.width
  }
}

onMounted(async () => {
  if (props.width) {
    dislogStyle.width = props.width;
  }
  await nextTick()
  if (dialogRef.value === null) {
    return
  }
  calculationDisplayPosition()
  setUpzIndex()
  const body = document.querySelector("body");
  if (body.append) {
    body.append(dialogRef.value);
  } else {
    body.appendChild(dialogRef.value);
  }

})

</script>

<style lang="scss" scoped>

.cy-dialog-enter-active {
  animation: xing .3s;
}

.cy-dialog-leave-active {
  animation: xing .3s reverse;
}

@keyframes xing {
  0% {
    transform: scale(0.5);
  }
  100% {
    transform: scale(1);
  }
}

.cy-dialog {
  position: absolute;
  height: max-content;
  border-radius: 10px;

  background-color: white;
  box-shadow: 0 4px 8px rgb(0 0 0 / 20%), 0 6px 20px rgb(0 0 0 / 19%);


  .cy-dialog__header {
    width: 100%;
    position: relative;
    cursor: move;
    background-color: white;
    border-radius: 10px;
    display: flex;
    justify-content: center;
    border-bottom: 1px solid;


    .cy-dialog__img {
      display: flex;
      justify-content: center;
      align-items: center;
      margin-right: 10px;

      img {
        width: 20px;
        height: 20px;
      }
    }


    .cy-dialog__title {
      line-height: 40px;
      text-align: center;
      font-size: 12px;
    }

    .cy-dialog__icon {
      padding: 10px 0;
      display: flex;
      position: absolute;
      width: content-box;
      top: 0;
      right: 5px;
      cursor: default;

      div {
        width: 12px;
        height: 12px;
        padding: 4px;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 10px;
        margin-left: 5px;


        &:hover {
          i {
            opacity: 1;
          }
        }

        i {
          font-size: 12px;
          color: black;
          transform: scale(0.8);
          opacity: 0;
          transition: opacity .2s;
        }
      }
    }
  }

  .cy-dialog__main {
    min-height: 50px;
    height: max-content;
    padding: 10px;
  }
}

.cy-dialog__fullScreen {
  width: 100%;
  height: 100%;
  margin: 0;
  border-radius: 0;
}


</style>
