import { useDocumentVisibility } from "ahooks";
import { uniqueId } from "lodash-es";
import { forwardRef, useEffect, useImperativeHandle, useRef } from "react";
import { dynamicLoadCss, dynamicLoadJs } from "../../utils";

/**
 * 视频播放组件
 */
const AliPlayer = forwardRef(({
  source = "",
  vid = "",
  playAuth = "",
  cover = "",
  width = "100%",
  height = "600px",
  autoplay = true,
  showProgress = true,
  isLive = false,
  playTime = 0,
  onEnded,
  onTimeupdate,
  onGetPlayerInstance,
  aliPlayerProps,
}, ref) => {
  const playerRef = useRef(null);
  const containerRef = useRef(null);
  const visibility = useDocumentVisibility();
  const className = useRef(uniqueId("_")).current;

  useImperativeHandle(ref, () => ({
    play: () => {
      playerRef.current && playerRef.current.play();
    },
    pause: () => {
      playerRef.current && playerRef.current.pause();
    },
    getPlayerInstance: () => playerRef.current,
  }));

  const onDisposeAliPlayer = () => {
    if (!playerRef.current)
      return;
    playerRef.current.dispose();
    playerRef.current = null;
  };

  const onCreateAliPlayer = async () => {
    if (!containerRef.current)
      return;
    if (!window.Aliplayer) {
      if (window?.base?.loadDynamicResource) {
        await window.base.loadDynamicResource({
          url: "https://g.alicdn.com/apsara-media-box/imp-web-player/2.27.0/aliplayer-min.js",
          type: "script",
          attr: { type: "text/javascript" },
        });
        await window.base.loadDynamicResource({
          url: "https://g.alicdn.com/apsara-media-box/imp-web-player/2.27.0/skins/default/aliplayer-min.css",
          type: "link",
          attr: { rel: "stylesheet", type: "text/css" },
        });
      }
      else {
        await dynamicLoadJs("https://g.alicdn.com/apsara-media-box/imp-web-player/2.27.0/aliplayer-min.js");
        await dynamicLoadCss("https://g.alicdn.com/apsara-media-box/imp-web-player/2.27.0/skins/default/aliplayer-min.css");
      }
    }

    onDisposeAliPlayer();

    const skinLayout = [
      { name: "bigPlayButton", align: "blabs", x: 30, y: 80 },
      { name: "H5Loading", align: "cc" },
      { name: "errorDisplay", align: "tlabs", x: 0, y: 0 },
      { name: "infoDisplay" },
      { name: "tooltip", align: "blabs", x: 0, y: 56 },
      { name: "thumbnail" },
      {
        name: "controlBar",
        align: "blabs",
        x: 0,
        y: 0,
        children: [
          { name: "playButton", align: "tl", x: 15, y: 12 },
          { name: "timeDisplay", align: "tl", x: 10, y: 7 },
          { name: "fullScreenButton", align: "tr", x: 10, y: 12 },
          { name: "setting", align: "tr", x: 15, y: 12 },
          { name: "volume", align: "tr", x: 5, y: 10 },
        ],
      },
    ];

    if (showProgress) {
      skinLayout[skinLayout.length - 1].children.unshift({
        name: "progress",
        align: "blabs",
        x: 0,
        y: 44,
      });
    }

    playerRef.current = new window.Aliplayer(
      {
        id: className,
        ...(source
          ? { source }
          : {
              vid,
              playauth: playAuth,
              qualitySort: "asc",
              format: "m3u8",
              encryptType: 1,
              mediaType: "video",
              isLive: true,
              rePlay: false,
              playsinline: true,
              controlBarVisibility: "hover",
            }),
        cover,
        width,
        height,
        autoplay,
        isLive,
        useH5Prism: true,
        skinLayout,
        ...aliPlayerProps,
      },
      (player) => {
        onGetPlayerInstance && onGetPlayerInstance(player);
        if (autoplay) {
          player.play();
        }

        player.on("ended", () => {
          onEnded && onEnded();
        });

        player.on("timeupdate", () => {
          onTimeupdate && onTimeupdate(player.getCurrentTime());
        });

        if (playTime > 0) {
          player.seek(playTime);
        }
      },
    );
  };

  useEffect(() => {
    if (source || (vid && playAuth)) {
      onCreateAliPlayer();
    }

    return () => {
      onDisposeAliPlayer();
    };
  }, [source, vid, playAuth]);

  useEffect(() => {
    if (visibility === "hidden") {
      playerRef.current && playerRef.current.pause();
    }
    else {
      playerRef.current && playerRef.current.play();
    }
  }, [visibility]);

  return (
    <div
      ref={containerRef}
      id={className}
      style={{ width, height }}
    />
  );
});

AliPlayer.displayName = "AliPlayer";

export default AliPlayer;
