import { IconMusic } from "@/assets/icons";
import { isWeixinBrowser } from "@/controllers/wxController";
import { useEditor } from "@/modules/editor";
import {
  PauseCircleOutlined,
  PlayCircleOutlined,
  SoundOutlined,
} from "@ant-design/icons-vue";
import { css } from "@linaria/core";

import { Button, Dropdown, Slider } from "ant-design-vue";
import { Howl } from "howler";
import { nanoid } from "nanoid";
import {
  defineComponent,
  reactive,
  ref,
  watch,
  onUnmounted,
  onMounted,
} from "vue";
import { bool, number } from "vue-types";
import { MusicOptions } from "./localMusic";
declare const WeixinJSBridge: any;
export const PageMusic = defineComponent({
  setup() {
    const { store, helper, controls, actions } = useEditor();
    const rootComp = helper.findRootComp();
    const volume =
      rootComp?.value.volume != undefined ? rootComp?.value.volume : 0.3;
    const state = reactive({
      playStatus: false,
      duration: 0,
      currentTime: 0,
      muted: true,
      volume: volume,
    });

    let audioKey = nanoid();
    let audioBgm = ref();

    const initAudioBgm = () => {
      audioBgm.value = null;
      const curAudio = MusicOptions.find((e) => {
        return e.value == rootComp?.value.music;
      });
      const src = curAudio?.src || "";
      audioBgm.value = new Howl({
        src: [src],
        loop: store.isEditMode ? false : true,
        preload: true,
        HTML5: true,
        volume: volume,
      });
      controls.mediaCtrl.setMediasInstance(audioKey, audioBgm.value);
      audioBgm.value.on("load", () => {
        state.duration = audioBgm.value.duration();
        if (!store.isEditMode) {
          if (isWeixinBrowser()) {
            WeixinJSBridge.invoke(
              "getNetworkType",
              {},
              () => {
                playAudio(true);
              },
              false
            );
          } else {
            playAudio(true);
          }
        }
      });
      audioBgm.value.on("loaderror", () => {
        console.log("音频加载失败");
      });
      audioBgm.value.on("playerror", () => {
        console.log("音频播放失败");
      });
      audioBgm.value.on("play", () => {
        controls.mediaCtrl.pauseOtherMedia(audioKey);
        if (!state.playStatus) {
          state.playStatus = true;
        }
        playStep();
      });
      audioBgm.value.on("pause", () => {
        audioRest();
      });
      audioBgm.value.on("end", () => {
        if (store.isEditMode) {
          audioRest();
        }
      });
      setTimeout(() => {
        checkAutoPlay();
      }, 500);
    };
    const checkAutoPlay = () => {
      const duration = audioBgm.value.duration();
      if (duration) {
        state.duration = duration;
      }
      if (!audioBgm.value || store.isEditMode) {
        return;
      }
      let playing = audioBgm.value.playing();
      if (!playing) {
        playAudio(true);
      }
    };
    const playStep = () => {
      if (!audioBgm.value) {
        return;
      }
      let playing = audioBgm.value.playing();
      if (!playing) {
        return;
      }
      let seek = audioBgm.value.seek();
      state.currentTime = seek;
      requestAnimationFrame(playStep);
    };

    const playAudio = async (status: boolean) => {
      if (!audioBgm.value) {
        return;
      }
      if (status) {
        audioBgm.value.play();
      } else {
        audioRest();
      }
      let playing = audioBgm.value.playing();
      if (status && playing) {
        state.playStatus = true;
        return;
      }
      state.playStatus = false;
    };
    watch(
      () => rootComp?.value.music,
      () => {
        audioRest();
        initAudioBgm();
      }
    );
    onMounted(() => {
      initAudioBgm();
    });
    onUnmounted(() => {
      audioRest();
      audioBgm.value = null;
      controls.mediaCtrl.removeMedia(audioKey);
    });
    const seekChange = (v: number) => {
      state.currentTime = v;
      audioBgm.value && audioBgm.value.seek(v);
    };
    const volumeChange = (v: number) => {
      state.volume = v;
      if (rootComp) {
        actions.updateCompData(rootComp, "value.volume", v);
      }
      audioBgm.value && audioBgm.value.volume(v);
    };
    const audioRest = () => {
      if (!audioBgm.value) {
        return;
      }
      let playing = audioBgm.value.playing();
      if (playing) {
        audioBgm.value.pause();
      }
      state.playStatus = false;
      state.currentTime = 0;
      audioBgm.value.seek(0);
    };
    return () => {
      const music = rootComp?.value.music;
      return (
        <div class={store.isEditMode ? MusicEditStyle : MusicStyle}>
          {store.isEditMode ? (
            <AudioPlayer
              key={music}
              playStatus={state.playStatus}
              volume={state.volume}
              onStatus={playAudio}
              onSeekChange={seekChange}
              onVolumeChange={volumeChange}
              duration={state.duration}
              currentTime={state.currentTime}
            />
          ) : (
            <div
              class={["music_button", state.playStatus ? "rotating" : ""]}
              onClick={() => {
                playAudio(!state.playStatus);
              }}
            >
              <IconMusic />
            </div>
          )}
        </div>
      );
    };
  },
});

const AudioPlayer = defineComponent({
  props: {
    volume: number(),
    playStatus: bool(),
    currentTime: number(),
    duration: number(),
  },
  emits: ["status", "seekChange", "volumeChange"],
  setup(props, { emit }) {
    const audioControl = (playStatus: boolean) => {
      emit("status", playStatus);
    };
    const seekChange = (v: any) => {
      emit("seekChange", v);
    };
    const volumeChange = (v: any) => {
      emit("volumeChange", v);
    };
    const formatTime = (secs?: number) => {
      if (!secs) {
        return "00:00";
      }
      secs = Math.round(secs);

      const minutes = Math.floor(secs / 60) || 0;
      const seconds = secs - minutes * 60 || 0;

      return (
        String(minutes).padStart(2, "0") +
        ":" +
        String(seconds).padStart(2, "0")
      );
    };
    const volumeSlider = () => {
      return (
        <div class={[VolumeSliderStyle]}>
          <div class={"h-100px pb-8px"}>
            <Slider
              tooltipVisible={false}
              min={0}
              max={1}
              step={0.1}
              vertical={true}
              value={props.volume}
              onChange={volumeChange}
            ></Slider>
          </div>
        </div>
      );
    };
    return () => {
      return (
        <div class={AudioPlayerStyle}>
          {!props.playStatus ? (
            <Button
              type="link"
              icon={<PlayCircleOutlined style={{ fontSize: "24px" }} />}
              onClick={() => audioControl(true)}
            ></Button>
          ) : (
            <Button
              type="link"
              icon={<PauseCircleOutlined style={{ fontSize: "24px" }} />}
              onClick={() => audioControl(false)}
            ></Button>
          )}
          <div class={"flex-1 px-10px"}>
            <Slider
              disabled={!props.playStatus}
              tooltipVisible={false}
              min={0}
              max={Math.floor(props.duration || 0)}
              value={props.currentTime}
              onChange={seekChange}
            ></Slider>
          </div>
          <div>
            {formatTime(props.currentTime)}/{formatTime(props.duration)}
          </div>
          <div>
            <Dropdown
              disabled={!props.playStatus}
              overlay={volumeSlider()}
              trigger="click"
              placement="top"
            >
              <Button
                type="link"
                icon={<SoundOutlined style={{ fontSize: "18px" }} />}
              ></Button>
            </Dropdown>
          </div>
        </div>
      );
    };
  },
});
const VolumeSliderStyle = css`
  margin-bottom: -4px;
  padding: 8px 4px;
  background-color: #303030;
  border-radius: 4px;
  box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.2);
  /* slider style */
  .ant-slider-disabled {
    opacity: 0.7;
  }
  .ant-slider-step {
    background-color: rgba(255, 255, 255, 0.27);
  }
  .ant-slider-track {
    border-radius: 4px;
    background-color: rgba(255, 255, 255, 1);
  }

  .ant-slider:not(.ant-slider-disabled):hover {
    .ant-slider-handle {
      background-color: @inf-primary-color;
      &:not(.ant-tooltip-open) {
        border-color: #fff;
      }
    }
  }
  .ant-slider {
    &.ant-slider-disabled {
      .ant-slider-handle {
        background-color: #bbb;
        opacity: 0.8;
      }
    }
  }
  .ant-slider-handle {
    width: 14px;
    height: 8px;
    border-radius: 2px;
    border-color: #fff;
    background-color: #fff;
  }

  .ant-slider-handle-click-focused {
    border-color: #fff;
    background-color: @inf-primary-color;
  }
`;
const MusicEditStyle = css`
  flex: 1;
`;
const AudioPlayerStyle = css`
  width: 100%;
  display: flex;
  align-items: center;

  /* slider style */
  .ant-slider-disabled {
    opacity: 0.7;
  }
  .ant-slider-step {
    background-color: rgba(255, 255, 255, 0.27);
  }
  .ant-slider-track {
    border-radius: 4px;
    background-color: rgba(255, 255, 255, 1);
  }

  .ant-slider:not(.ant-slider-disabled):hover {
    .ant-slider-handle {
      background-color: @inf-primary-color;
      &:not(.ant-tooltip-open) {
        border-color: #fff;
      }
    }
  }
  .ant-slider {
    &.ant-slider-disabled {
      .ant-slider-handle {
        background-color: #bbb;
        opacity: 0.8;
      }
    }
  }
  .ant-slider-handle {
    width: 8px;
    border-radius: 2px;
    border-color: #fff;
    background-color: #fff;
  }

  .ant-slider-handle-click-focused {
    border-color: #fff;
    background-color: @inf-primary-color;
  }
`;
const MusicStyle = css`
  position: fixed;
  top: 10px;
  right: 10px;
  z-index: 999;
  .music_button {
    width: 48px;
    height: 48px;
    display: inline-flex;
    justify-content: center;
    align-items: center;
    background-color: rgba(0, 0, 0, 0.5);
    font-size: 28px;
    border-radius: 24px;
    cursor: pointer;
    &.rotating {
      animation: myRotate 5s linear infinite;
    }
  }
  @keyframes myRotate {
    0% {
      transform: rotate(0);
    }
    100% {
      transform: rotate(360deg);
    }
  }
`;
