<template>
  <div class="live2d_canvas" v-show="show" :style="position">
    <slot name="info">
      <div class="info" v-show="isInfo" style="width: 150px">
        {{ showMess }}
      </div>
    </slot>
    <div class="wrap">
      <canvas
        :id="canvasId"
        width="150"
        height="300"
        @mousedown="mousedown"
        @touchstart.passive="mousedown"
        @mouseup="mouseup"
        @touchend="mouseup"
      ></canvas>
      <slot name="tool">
        <div class="tool">
          <p @click="nextScene">换</p>
          <p @click="autoSpeak">说</p>
        </div>
      </slot>
    </div>
  </div>
</template>
<script>
import {
  // ref,
  reactive,
  computed,
  toRefs,
  onBeforeMount,
  onMounted,
  onActivated,
  onUpdated,
  onUnmounted,
  onDeactivated,
  watch,
  toRaw,
  nextTick,
} from "vue";
import "./bundle.js";
export default {
  props: {
    position: {
      type: String,
      default: "bottom: 10px;right: 10px;",
    },
    show: {
      type: Boolean,
      default: true,
    },
    live2dcubismcore: {
      //live2dcubismcore 路径
      type: String,
      default: "live2d/core/live2dcubismcore.min.js",
    },
    resourcesPath: {
      //模型根路径
      type: String,
      default: "live2d/resources/",
    },
    modelDir: {
      type: Array,
      default: ["Haru", "Hiyori"],
    },
    backImageName: {
      //背景图片
      type: String,
      default: "",
    },
    gearImageName: {
      //右上角齿轮
      type: String,
      default: null,
    },
    debugLogEnable: {
      //debug
      type: Boolean,
      default: true,
    },
    headMessage: {
      type: Array,
      default: [
        "摸摸头",
        "讨厌~不要掐人家的脸嘛~",
        "希望明天也能感受到你的触摸呢",
      ],
    },
    bodyMessage: {
      type: Array,
      default: ["别乱摸", "啊呀，你的手在摸哪里嘛~", "哼，坏人"],
    },
    defaultMessage: {
      type: Array,
      default: ["我是谁", "今天又是开心的一天呢~", "真是元气满满呀"],
    },
    isGlobal: {
      // 模型是否跟随全局鼠标移动
      type: Boolean,
      default: true,
    },
    isAuto: {
      // 是否自动显示预设文案
      type: Boolean,
      default: true,
    },
    autoSpeakTime: {
      //自动切换语言时间
      type: Number,
      default: 5000,
    },
  },
  setup(props, { emit, slots, attrs }) {
    let state = reactive({
      canvasId:
        "live2d" +
        new Date().getTime() +
        "_" +
        Math.floor(Math.random() * 100 + 1),
      canvasInfo: {},
      LAppLive2DManagerGetInstance: {},
      LAppDefine: {},
      LAppDelegateGetInstance: {},
      LAppView: {},
      LAppTouchManager: {},
      showMess: "",
      isInfo: false,
    });
    const insertScript = (src) => {
      return new Promise((resolve, reject) => {
        let scripts = [...document.getElementsByTagName("script")];
        let isHave = false;
        scripts.forEach((item) => {
          if (item.src.indexOf(src) > -1) isHave = true;
        });
        if (!isHave) {
          const elem = document.createElement("script");
          elem.type = "text/javascript";
          elem.src = src;
          elem.onload = elem.onreadystatechange = function () {
            resolve({ src, mess: "success" });
          };
          elem.onerror = function (err) {
            reject(err);
          };
          document.getElementsByTagName("head")[0].appendChild(elem);
        } else {
          resolve({ src });
        }
      });
    };
    let initTimer = null,
      initFail = 0;
    const initLive2d = () => {
      const {
        Live2d: { LAppDefine, LAppDelegate, LAppLive2DManager },
        Live2DCubismCore,
      } = window;
      if (!Live2DCubismCore) {
        initFail++;
        initTimer = setTimeout(() => {
          console.log("初始化 initLive2d失败 在回调", initFail);
          initLive2d();
          clearTimeout(initTimer);
        }, 500);
        return;
      }
      const { canvasId, canvasInfo } = state;
      const {
        resourcesPath,
        backImageName,
        gearImageName,
        debugLogEnable,
        modelDir,
        isAuto,
      } = props;
      const LAppDelegateGetInstance = LAppDelegate.getInstance(),
        LAppView = LAppDelegateGetInstance._view,
        LAppTouchManager = LAppDelegateGetInstance._view._touchManager;
      LAppDefine.CanvasId = canvasId;
      LAppDefine.ModelDir = modelDir;
      LAppDefine.ModelDirSize = modelDir.length;
      LAppDefine.CanvasSize = {
        width: canvasInfo.width,
        height: canvasInfo.height,
      }; //画布大小 默认值auto,resize会铺满全屏
      LAppDefine.ResourcesPath = resourcesPath; //模型路径
      LAppDefine.BackImageName = backImageName; //背景图片
      LAppDefine.GearImageName = gearImageName; //右上角齿轮
      LAppDefine.DebugLogEnable = debugLogEnable; //debug
      if (LAppDelegateGetInstance.initialize(canvasId) == false) {
        return;
      }
      LAppDelegateGetInstance.run(true); //canvas背景透明
      state.LAppLive2DManagerGetInstance = LAppLive2DManager.getInstance(); //必须在LAppDelegateGetInstance初始化之后调用;
      state.LAppDefine = LAppDefine;
      state.LAppDelegate = LAppDelegate;
      state.LAppDelegateGetInstance = LAppDelegateGetInstance;
      state.LAppView = LAppView;
      state.LAppTouchManager = LAppTouchManager;

      console.log("LAppDelegate", LAppDelegate);
      console.log("LAppDelegate", LAppDelegateGetInstance);

      isAuto && autoSpeak();
      addEventListener();
    };
    const nextScene = () => {
      state.LAppLive2DManagerGetInstance.nextScene(); //切换下一个模型
    };
    const changeScene = (number) => {
      state.LAppLive2DManagerGetInstance.changeScene(number); //切换指定模型
    };
    let isAutoSpeak = false,
      setInter = null;
    const autoSpeak = () => {
      if (isAutoSpeak) {
        isAutoSpeak = false;
        state.isInfo = false;
        state.showMess = "";
        clearInterval(setInter);
        return;
      }
      const { defaultMessage, autoSpeakTime } = props;
      state.showMess = randomMessage("defaultMessage");
      state.isInfo = true;
      isAutoSpeak = true;
      setInter = setInterval(() => {
        state.showMess = randomMessage("defaultMessage");
      }, autoSpeakTime);
    };

    const addEventListener = () => {
      const dom = document;
      dom.addEventListener("resize", globalResize, false);
      if (!props.isGlobal) return;
      dom.addEventListener("mousemove", globalMouseMove, false);
      dom.addEventListener("mouseout", globalMouseOut, false);
    };
    const removeEventListener = () => {
      const dom = document;
      dom.removeEventListener("resize", globalResize, false);
      if (!props.isGlobal) return;
      dom.removeEventListener("mousemove", globalMouseMove, false);
      dom.removeEventListener("mouseout", globalMouseOut, false);
    };
    const globalResize = () => {
      if (state.LAppDefine.CanvasSize === "auto") {
        state.LAppDelegateGetInstance.onResize();
      }
    };
    const globalMouseMove = (e) => {
      if (!state.LAppView) {
        return;
      }
      const rect = state.canvasInfo;
      if (rect) {
        const posX = e.clientX - rect.left;
        const posY = e.clientY - rect.top;
        state.LAppView.onTouchesMoved(posX, posY);
      }
    };
    const globalMouseOut = (e) => {
      state.LAppLive2DManagerGetInstance.onDrag(0.0, 0.0);
    };
    const mouseup = (e) => {};
    let setTime = null;
    const mousedown = (e) => {
      if (setInter) {
        isAutoSpeak = false;
        clearInterval(setInter);
      }
      if (setTime) {
        clearTimeout(setTime);
      }
      setTime = setTimeout(() => {
        const {
          LAppLive2DManagerGetInstance: { hitArea },
          LAppDefine,
        } = state;
        if (hitArea === LAppDefine.HitAreaNameHead) {
          // 触摸头部
          showMessage("headMessage");
        } else if (hitArea === LAppDefine.HitAreaNameBody) {
          // 触摸身体
          showMessage("bodyMessage");
        } else {
          // 默认事件
          showMessage("defaultMessage");
        }
        clearTimeout(setTime);
      }, 250);
    };
    const showMessage = (type) => {
      state.showMess = randomMessage(type);
      state.isInfo = true;
      const timer = setTimeout(() => {
        state.isInfo = false;
        state.showMess = "";
        clearTimeout(timer);
      }, 2000);
    };
    const randomMessage = (type) => {
      const info = props[type];
      return info[Math.floor(Math.random() * info.length)];
    };
    const initLive2dInfo = (type) => {
      if (type) {
        // 初始化
        state.canvasInfo = document
          .getElementById(state.canvasId)
          .getBoundingClientRect();
        initLive2d();
      } else {
        // 清除
        clearInterval(setInter);
        removeEventListener();
        state.LAppLive2DManagerGetInstance.releaseAllModel(); //清除原来显示的模型
        state.LAppDelegateGetInstance.resetInstance();
      }
    };
    onBeforeMount(async () => {
      if (!window.Live2DCubismCore) {
        await insertScript(props.live2dcubismcore);
      }
    });
    onMounted(() => {
      initLive2dInfo(true);
    });
    onActivated(() => {
      console.log("keep-alive缓存组件被调用");
      initLive2dInfo(true);
    });
    onUnmounted(() => {
      console.log("卸载");
      initLive2dInfo(false);
    });
    onDeactivated(() => {
      console.log("keep-alive缓存组件被停用");
      initLive2dInfo(false);
    });
    return {
      ...toRefs(state),
      nextScene,
      changeScene,
      mouseup,
      mousedown,
      autoSpeak,
    };
  },
};
</script>

<style scoped>
.live2d_canvas {
  position: fixed;
}

.live2d_canvas .info {
  padding: 5px 10px;
  min-height: 40px;
  font-size: 14px;
  word-break: break-all;
  text-overflow: ellipsis;
  border: 1px solid rgba(224, 186, 140, 0.62);
  border-radius: 12px;
  background-color: rgba(236, 217, 188, 0.5);
}
.live2d_canvas .wrap {
  display: flex;
  cursor: pointer;
  transform: translateX(40px);
  transition: transform 0.3s ease-in-out;
}
.live2d_canvas .wrap .tool {
  width: 40px;
  text-align: center;
}
.live2d_canvas .wrap .tool p {
  height: 40px;
  line-height: 40px;
}

.live2d_canvas .wrap:hover {
  transform: translateX(0);
}
</style>