<!-- eslint-disable vue/define-macros-order -->
<script setup lang="ts">
import { globalBack } from '@/router'
import { ref } from 'vue'

const defaultBg = 'rgba(0, 0, 0, 0.45)'
const defaultText = '正在加载中...'

// 属性
const props = withDefaults(defineProps<MjLoadingProps>(), {
  modelValue: false,
  text: defaultText,
  background: defaultBg,
  duration: true,
  fullscreen: false,
  showBack: undefined,
})
// 事件
const emits = defineEmits(['update:modelValue'])
// 方法
type Func = () => void

export type MjLoadingOptions = {
  text?: string
  background?: string
  duration?: boolean
  fullscreen?: boolean
  showBack?: boolean
  back?: (fn: Func) => void
}
// 组件属性
export type MjLoadingProps = {
  modelValue?: boolean
} & MjLoadingOptions

const js_props = ref({} as MjLoadingOptions)
// 组件模式
const mode_cmp = 0
// js模式
const mode_js = 1
const mode = ref(mode_cmp)
const options = computed(() => {
  return (mode.value === mode_cmp ? props : js_props.value) as MjLoadingOptions
})

// 是否可见
const js_visible = ref(false)
const visible = computed({
  get() {
    return mode.value === mode_js ? js_visible.value : props.modelValue
  },
  set(newVal) {
    if (mode.value === mode_js) {
      js_visible.value = newVal
    } else {
      emits('update:modelValue', newVal)
    }

    // if (newVal) {
    //     showText()
    // }
  },
})

// 是否显示返回
const _showBack = computed(() => {
  if (options.value.showBack !== undefined) return options.value.showBack
  return options.value.fullscreen || !!options.value.back
})

// 需要动态修改的数据，需要单独列出状态
const _text = ref('')
const timer = ref<any>()

watch(
  () => visible.value,
  newVal => {
    if (!newVal) return
    showText()
  },
  { immediate: true },
)

function showText() {
  // 显示
  _text.value = options.value.text as any
  let time = 0
  if (options.value.duration) {
    // 需要显示时间
    timer.value = setInterval(() => {
      time += 1
      _text.value = `${options.value.text}（${time}s）`
    }, 1000)
  }
}

function _back() {
  const fn = () => {
    hide()
    globalBack()
  }
  if (options.value.back) {
    options.value.back(fn)
  } else {
    fn()
  }
}

function clearTimer() {
  if (timer.value) {
    clearInterval(timer.value)
  }
}

function hide() {
  visible.value = false
  js_props.value = {} as MjLoadingOptions
  clearTimer()
}
// onMounted(() => {
//     // if (props.modelValue) {
//     //     showText()
//     // }
// })

onUnmounted(hide)

defineExpose({
  show: (data: MjLoadingOptions | string) => {
    clearTimer()

    // 设置模式
    mode.value = mode_js
    // 参数处理
    if (typeof data === 'string') {
      data = {
        text: data,
      }
    }
    // 默认值设置
    if (!data.text) {
      data.text = defaultText
    }
    if (!data.background) {
      data.background = defaultBg
    }
    if (data.duration === undefined) {
      data.duration = true
    }
    // 统一赋值
    js_props.value = data
    // 显示
    visible.value = true
  },
  hide,
  isShowing: () => visible.value,
})
</script>

<template>
  <div
    v-if="visible"
    class="mj-loading"
    :class="{
      'g-main-bg': options.fullscreen,
    }"
    :style="
      options.fullscreen
        ? {}
        : {
            background: options.background,
          }
    "
  >
    <Icon v-if="_showBack" class="back" name="left_arrow" :size="80" @click="_back" />
    <div class="spinner">
      <Icon class="icon" name="global_loading" loading :size="options.fullscreen ? 180 : 128" />
      <p class="text">{{ _text }}</p>
    </div>
  </div>
</template>

<style lang="scss" scoped>
$filter: brightness(0) saturate(0) invert(0) sepia(0) hue-rotate(30deg);
.mj-loading {
  position: fixed;
  bottom: 0;
  left: 0;
  margin: 0;
  right: 0;
  top: 0;
  transition: opacity 0.3s;
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 100000000000;
  text-align: center;

  .icon {
    margin-bottom: 2.5vh;
  }

  .text {
    color: #fff;
    font-size: 3vh;
    font-family: $font-special;
  }

  &.g-main-bg {
    .back {
      position: absolute;
      top: 2.67vh;
      left: 64px;
    }

    .spinner {
      .text {
        font-size: 4vh;
        font-family: $font-special;
        color: $font-color;
        text-align: center;
        text-shadow: 0 0.17vh 0.17vh rgba(0, 0, 0, 0.25);
      }

      .x-icon {
        filter: $filter;
      }
    }
  }
}
</style>
