import {
  defineComponent,
  nextTick,
  onMounted,
  onUnmounted,
  reactive,
  watch,
  ref
} from 'vue';
// import WaveSurfer from 'wavesurfer.js';
import styles from './index.module.less';
import MSticky from '@/components/m-sticky';
import MHeader from '@/components/m-header';
import {
  Button,
  Cell,
  Image,
  List,
  Popup,
  Slider,
  showDialog,
  showToast,
  Sticky,
  TextEllipsis
} from 'vant';
import iconDownload from './images/icon-download.png';
import iconShare from './images/icon-share.png';
import iconDelete from './images/icon-delete.png';
import iconEdit from './images/edit.png';
import iconUpward from './images/upward.png';
import iconMember from './images/icon-member.png';
import iconZan from './images/icon-zan.png';
import promptImg from './images/prompt.png';
import confirmImg from './images/confirm.png';
import canceImg from './images/cance.png';
import iconZanActive from './images/icon-zan-active.png';
import iconPlay from './images/icon-play.png';
import iconPause from './images/icon-pause.png';
import { postMessage, promisefiyPostMessage } from '@/helpers/native-message';
import { browser, getGradeCh, getSecondRPM, vaildMusicScoreUrl } from '@/helpers/utils';
import { useRoute, useRouter, onBeforeRouteLeave } from 'vue-router';
import {
  api_userMusicDetail,
  api_userMusicRemove,
  api_userMusicStarPage
} from './api';
import MEmpty from '@/components/m-empty';
import dayjs from 'dayjs';
import MVideo from '@/components/m-video';
import ShareModel from './share-model';
import { usePageVisibility, useEventListener } from '@vant/use';
import "plyr/dist/plyr.css";
import Plyr from "plyr";
import { Vue3Lottie } from "vue3-lottie";
import audioBga from "./images/audioBga.json";
import audioBga1 from "./images/leftCloud.json";
import audioBga2 from "./images/rightCloud.json";
import videobg from "./images/videobg.png";
import playProgressData from "./playCreation/playProgress"
import Loading from './loading';
import { generateMixedData } from "./audioVisualDraw"

export default defineComponent({
  name: 'creation-detail',
  setup() {
    const route = useRoute();
    const router = useRouter();
    const isScreenScroll = ref(false)
    const mStickyBottom = ref()
    const mStickyUpward = ref()
    const state = reactive({
      id: route.query.id,
      deleteStatus: false,
      shareStatus: false,
      playType: '' as 'Audio' | 'Video' | '', // 播放类型
      musicDetail: {} as any,
      isClick: false,
      list: [] as any,
      listState: {
        dataShow: true, // 判断是否有数据
        loading: false,
        finished: false
      },
      params: {
        page: 1,
        rows: 20
      },
      _plrl: null as any,
      heightV:0,
      heightB:0
    });
    const plyrState = reactive({
      duration: 0,
      currentTime: 0,
      mediaTimeShow: false,
      playIngShow: true
    })
    // 谱面
    const staffState = reactive({
      staffSrc: "",
      isShow: false,
      height:"initial",
      speedRate:1,
      musicRenderType:"staff",
      partIndex: 0
    })
    const staffDom= ref<HTMLIFrameElement>()
    const {playStaff, pauseStaff, updateProgressStaff} = staffMoveInstance()
    // 获取列表
    const getStarList = async () => {
      try {
        if (state.isClick) return;
        state.isClick = true;
        const res = await api_userMusicStarPage({
          userMusicId: state.id,
          ...state.params
        });
        state.listState.loading = false;
        const result = res.data || {};
        // 处理重复请求数据
        if (state.list.length > 0 && result.current === 1) {
          return;
        }
        state.list = state.list.concat(result.rows || []);
        state.listState.finished = result.current >= result.pages;
        state.params.page = result.current + 1;
        state.listState.dataShow = state.list.length > 0;
        state.isClick = false;
      } catch {
        state.listState.dataShow = false;
        state.listState.finished = true;
        state.isClick = false;
      }
    };
    // 删除作品
    const onDelete = async () => {
      try {
        await api_userMusicRemove({ id: state.id });
        setTimeout(() => {
          state.deleteStatus = false;
          showToast('删除成功');
        }, 100);

        setTimeout(() => {
          if (browser().isApp) {
            postMessage({
              api: 'goBack'
            });
          } else {
            router.back();
          }
        }, 1200);
      } catch {
        //
      }
    };

    // 下载
    const onDownload = async () => {
      await promisefiyPostMessage({
        api: 'saveFile',
        content: {
          url: state.musicDetail.videoUrl
        }
      });
    };
    // 滚动事件
    const cleanScrollEvent = useEventListener('scroll', () => {
      const height =
        window.scrollY ||
        document.documentElement.scrollTop
        // 防止多次调用
        if(height > 0 && isScreenScroll.value === false){
          isScreenScroll.value = true
          setStatusBarTextColor(false)
        }
        if(height <= 0){
          isScreenScroll.value = false
          setStatusBarTextColor(true)
        }
    })
    // 设置导航栏颜色
    function setStatusBarTextColor(isWhite:boolean){
      postMessage({
        api: 'setStatusBarTextColor',
        content: { statusBarTextColor: isWhite }
      })
    }
    // 初始化 媒体播放
    function initMediaPlay(){
      const id = state.playType === "Audio" ? "#audioMediaSrc" : "#videoMediaSrc";
      state._plrl = new Plyr(id, {
        controls: ["progress"],
        fullscreen: {
          enabled: false,
          fallback: false
        }
      });
      const player = state._plrl
        // 创建音波数据
      if(state.playType === "Audio"){
        const audioDom = document.querySelector("#audioMediaSrc") as HTMLAudioElement
        const canvasDom = document.querySelector("#audioVisualizer") as HTMLCanvasElement
        const { pauseVisualDraw, playVisualDraw } = audioVisualDraw(audioDom, canvasDom)
        player.on('play', () => {
          playVisualDraw()
        });
        player.on('pause', () => {
          pauseVisualDraw()
        });
      }
      player.on('loadedmetadata', () => {
        player.currentTime = playProgressData.playProgress
      });
      player.on("timeupdate", ()=>{
        plyrState.currentTime = player.currentTime
      })
      player.on('play', () => {
        plyrState.playIngShow = false
        playStaff()
      });
      player.on('pause', () => {
        plyrState.playIngShow = true
        pauseStaff()
      });
      player.on('ended', () => {
        player.currentTime = 0
        if(!player.playing){
          setTimeout(() => {
            updateProgressStaff(player.currentTime)
          }, 100);
        }
      });
      // 处理按压事件
      const handleStart = () => {
        plyrState.duration = player.duration
        plyrState.mediaTimeShow = true
      };
      // 处理松开事件
      const handleEnd = () => {
        plyrState.mediaTimeShow = false
        // 暂停的时候调用
        if(!player.playing){
          updateProgressStaff(player.currentTime)
        }
      };
      const progressDom = document.querySelector("#playMediaSection .plyr__controls .plyr__progress__container") as HTMLElement
      progressDom.addEventListener('mousedown', handleStart);
      progressDom.addEventListener('touchstart', handleStart);
      progressDom.addEventListener('mouseup', handleEnd);
      progressDom.addEventListener('touchend', handleEnd);
    }
    //点击改变播放状态
    function handlerClickPlay(){
      if (state._plrl.playing) {
        state._plrl.pause();
      } else {
        state._plrl.play();
      }
    }
    /**
		 * 音频可视化
		 * @param audioDom
		 * @param canvasDom
		 * @param fftSize  2的幂数，最小为32
		 */
    function audioVisualDraw(audioDom: HTMLAudioElement, canvasDom: HTMLCanvasElement, fftSize = 128) {
      type propsType = { canvWidth: number; canvHeight: number; canvFillColor: string; lineColor: string; lineGap: number }
      // canvas
      const canvasCtx = canvasDom.getContext("2d")!
      const { width, height } = canvasDom.getBoundingClientRect()
      canvasDom.width = width
      canvasDom.height = height
      // audio
      // let audioCtx : AudioContext | null = null
      // let analyser : AnalyserNode | null = null
      // let source : MediaElementAudioSourceNode | null = null
      // const dataArray = new Uint8Array(fftSize / 2)
      const draw = (data: Uint8Array, ctx: CanvasRenderingContext2D, { lineGap, canvWidth, canvHeight, canvFillColor, lineColor }: propsType) => {
        if (!ctx) return
        const w = canvWidth
        const h = canvHeight
        fillCanvasBackground(ctx, w, h, canvFillColor)
          // 可视化
        const dataLen = data.length
        let step = (w / 2 - lineGap * dataLen) / dataLen
        step < 1 && (step = 1)
        const midX = w / 2
        const midY = h / 2
        let xLeft = midX
        for (let i = 0; i < dataLen; i++) {
          const value = data[i]
          const percent = value / 255 // 最大值为255
          const barHeight = percent * midY
          canvasCtx.fillStyle = lineColor
          // 中间加间隙
          if (i === 0) {
            xLeft -= lineGap / 2
          }
          canvasCtx.fillRect(xLeft - step, midY - barHeight, step, barHeight)
          canvasCtx.fillRect(xLeft - step, midY, step, barHeight)
          xLeft -= step + lineGap
        }
        let xRight = midX
        for (let i = 0; i < dataLen; i++) {
          const value = data[i]
          const percent = value / 255 // 最大值为255
          const barHeight = percent * midY
          canvasCtx.fillStyle = lineColor
          if (i === 0) {
            xRight += lineGap / 2
          }
          canvasCtx.fillRect(xRight, midY - barHeight, step, barHeight)
          canvasCtx.fillRect(xRight, midY, step, barHeight)
          xRight += step + lineGap
        }
      }
      const fillCanvasBackground = (ctx: CanvasRenderingContext2D, w: number, h: number, colors: string) => {
        ctx.clearRect(0, 0, w, h)
        ctx.fillStyle = colors
        ctx.fillRect(0, 0, w, h)
      }
      const requestAnimationFrameFun = () => {
        // requestAnimationFrame(() => {
        //   //analyser?.getByteFrequencyData(dataArray)
        //   draw(generateMixedData(48), canvasCtx, {
        //     lineGap: 2,
        //     canvWidth: width,
        //     canvHeight: height,
        //     canvFillColor: "transparent",
        //     lineColor: "rgba(255, 255, 255, 0.7)"
        //   })
        //   if (!isPause) {
        //     requestAnimationFrameFun()
        //   }
        // })
        const _time = setInterval(() => {
          if (isPause) {
            clearInterval(_time)
            return
          }
          //analyser?.getByteFrequencyData(dataArray)
          draw(generateMixedData(38), canvasCtx, {
            lineGap: 3,
            canvWidth: width,
            canvHeight: height,
            canvFillColor: "transparent",
            lineColor: "rgba(255, 255, 255, 0.7)"
          })
        }, 300);
      }
      let isPause = true
      const playVisualDraw = () => {
        // if (!audioCtx) {
        //   audioCtx = new AudioContext()
        //   source = audioCtx.createMediaElementSource(audioDom)
        //   analyser = audioCtx.createAnalyser()
        //   analyser.fftSize = fftSize
        //   source?.connect(analyser)
        //   analyser.connect(audioCtx.destination)
        // }
        //audioCtx.resume()  // 重新更新状态   加了暂停和恢复音频音质发生了变化  所以这里取消了
        isPause = false
        requestAnimationFrameFun()
      }
      const pauseVisualDraw = () => {
        isPause = true
        requestAnimationFrame(()=>{
          canvasCtx.clearRect(0, 0, width, height);
        })
        //audioCtx?.suspend()  // 暂停   加了暂停和恢复音频音质发生了变化  所以这里取消了
        // source?.disconnect()
        // analyser?.disconnect()
      }
      return {
        playVisualDraw,
        pauseVisualDraw
      }
    }
    function handlerLandscapeScreen(event:any){
      event.stopPropagation()
      playProgressData.playState = !!state._plrl?.playing
      playProgressData.playProgress = state._plrl?.currentTime || 0
      router.push({
        path:"/playCreation",
        query:{
          resourceUrl:encodeURIComponent(state.musicDetail?.videoUrl),
          videoBgUrl:encodeURIComponent(state.musicDetail?.videoImg || ""),
          musicSheetName:encodeURIComponent(state.musicDetail?.musicSheetName),
          username:encodeURIComponent(state.musicDetail?.username),
          musicSheetId:encodeURIComponent(state.musicDetail?.musicSheetId),
          speedRate:encodeURIComponent(staffState.speedRate),
          musicRenderType:encodeURIComponent(staffState.musicRenderType),
          partIndex:encodeURIComponent(staffState.partIndex),
        }
      })
    }
    // 初始化五线谱
    function initStaff(){
      const src = `${vaildMusicScoreUrl()}/instrument/#/simple-detail?id=${state.musicDetail.musicSheetId}&musicRenderType=${staffState.musicRenderType}&part-index=${staffState.partIndex}`;
      //const src = `http://192.168.3.122:3000/instrument.html#/simple-detail?id=${state.musicDetail.musicSheetId}&musicRenderType=${staffState.musicRenderType}&part-index=${staffState.partIndex}`;
      staffState.staffSrc = src
      window.addEventListener('message', (event) => {
        const { api, height } = event.data;
        if (api === 'api_musicPage') {
          staffState.isShow = true
          staffState.height = height + "px"
          // 如果是播放中自动开始播放  不是播放 自动跳转到当前位置
          if(playProgressData.playState){
            handlerClickPlay()
          }else{
            updateProgressStaff(state._plrl.currentTime)
          }
        }
      });
    }
    function staffMoveInstance(){
      let isPause = true
      const requestAnimationFrameFun = () => {
				requestAnimationFrame(() => {
          staffDom.value?.contentWindow?.postMessage(
            {
              api: 'api_playProgress',
              content: {
                currentTime: state._plrl.currentTime * staffState.speedRate
              }
            },
            "*"
          )
					if (!isPause) {
						requestAnimationFrameFun()
					}
				})
			}
      const playStaff = () => {
        // 没渲染不执行
        if(!staffState.isShow) return
				isPause = false
        staffDom.value?.contentWindow?.postMessage(
          {
            api: 'api_play'
          },
          "*"
        )
				requestAnimationFrameFun()
			}
			const pauseStaff = () => {
        // 没渲染不执行
        if(!staffState.isShow) return
				isPause = true
        staffDom.value?.contentWindow?.postMessage(
          {
            api: 'api_paused'
          },
          "*"
        )
			}
      const updateProgressStaff = (currentTime: number) => {
        // 没渲染不执行
        if(!staffState.isShow) return
        staffDom.value?.contentWindow?.postMessage(
          {
            api: 'api_updateProgress',
            content: {
              currentTime: currentTime * staffState.speedRate
            }
          },
          "*"
        )
      }
			return {
				playStaff,
				pauseStaff,
        updateProgressStaff
			}
    }
    onMounted(async () => {
      setStatusBarTextColor(true)
      try {
        const res = await api_userMusicDetail(state.id);
        // console.log(res);
        if (res.code === 999) {
          showDialog({
            message: res.message,
            theme: 'round-button',
            confirmButtonColor:
              'linear-gradient(73deg, #5BECFF 0%, #259CFE 100%)'
          }).then(() => {
            if (browser().isApp) {
              postMessage({
                api: 'goBack'
              });
            } else {
              router.back();
            }
          });
          return;
        }
        state.musicDetail = res.data || {};
        try{
          const jsonConfig = JSON.parse(res.data.jsonConfig)
          jsonConfig.speedRate && (staffState.speedRate = jsonConfig.speedRate)
          jsonConfig.musicRenderType && (staffState.musicRenderType = jsonConfig.musicRenderType)
          jsonConfig.partIndex && (staffState.partIndex = jsonConfig.partIndex)
        }catch{
        }
        // 五线谱
        initStaff()
        getStarList();
        // 判断是视频还是音频
        if (res.data.videoUrl.lastIndexOf('mp4') !== -1) {
          state.playType = 'Video';
        } else {
          state.playType = 'Audio';
        }
        nextTick(()=>{
          initMediaPlay()
        })
      } catch {
        //
      }
      requestAnimationFrame(()=>{
        mStickyBottom.value?.onChnageHeight()
        mStickyBottom.value?.onChnageHeight()
      })
    });

    onUnmounted(() => {
      cleanScrollEvent()
      state._plrl?.destroy()
    });
    onBeforeRouteLeave((to, from, next)=>{
      if(to.path !== "/playCreation"){
        playProgressData.playProgress = 0
        playProgressData.playState = false
      }
      next()
    })
    return () => (
      <div
        style={
          {
            '--barheight':state.heightV + "px"
          }
        }
        class={[
          styles.creation,
          browser().isTablet && styles.creationTablet,
          isScreenScroll.value && styles.isScreenScroll
        ]}>
        <div class={styles.creationBg}></div>
        <MSticky position="top"
          onBarHeight={(height: any) => {
            console.log(height, 'height', height)
            state.heightV = height
          }}
        >
          <MHeader
            color={isScreenScroll.value ? "#333333" : "#ffffff"}
            background={isScreenScroll.value ? `rgb(255,255,255` : "transparent"}
            title={state.musicDetail?.musicSheetName}
            border={false}
            isBack={route.query.platformType != 'ANALYSIS'}
            onLeftClick={()=>{ setStatusBarTextColor(false) }}
          />
        </MSticky>
        <div class={styles.singer}>
          演奏：{state.musicDetail?.username}
        </div>
        <Sticky offsetTop={state.heightV - 1 + "px"}>
          <div class={[styles.playSection, plyrState.mediaTimeShow && styles.mediaTimeShow]} id="playMediaSection" onClick={handlerClickPlay}>
            {
              state.playType === 'Audio' &&
              <div class={styles.audioBox}>
                <canvas class={styles.audioVisualizer} id="audioVisualizer"></canvas>
                <Vue3Lottie class={styles.audioBga} animationData={audioBga} autoPlay={true} loop={true}></Vue3Lottie>
                <Vue3Lottie class={styles.audioBga1} animationData={audioBga1} autoPlay={true} loop={true}></Vue3Lottie>
                <Vue3Lottie class={styles.audioBga2} animationData={audioBga2} autoPlay={true} loop={true}></Vue3Lottie>
                <audio
                  crossorigin="anonymous"
                  id="audioMediaSrc"
                  src={state.musicDetail?.videoUrl}
                  controls="false"
                  preload="metadata"
                  playsinline
                  webkit-playsinline
                />
              </div>
            }
            {
              state.playType === 'Video' &&
              <video
                id="videoMediaSrc"
                class={styles.videoBox}
                src={state.musicDetail?.videoUrl}
                data-poster={ state.musicDetail?.videoImg || videobg}
                preload="metadata"
                playsinline
              />
            }
            <div class={[styles.playLarge, !plyrState.mediaTimeShow && plyrState.playIngShow && styles.playIngShow]}></div>
            <div class={styles.mediaTimeCon}>
              <div class={styles.mediaTime}>
                <div>
                  {getSecondRPM(plyrState.currentTime)}
                </div>
                <div class={styles.note}>/</div>
                <div class={styles.duration}>
                  {getSecondRPM(plyrState.duration)}
                </div>
              </div>
            </div>
            <div class={styles.landscapeScreen} onClick={handlerLandscapeScreen}></div>
            {/* 谱面 */}
            {
              staffState.staffSrc &&
              <div class={[styles.staffBoxCon, staffState.isShow && styles.staffBoxShow]}>
                <div
                  class={styles.staffBox}
                  style={
                    {
                      '--staffBoxHeight':staffState.height
                    }
                  }
                >
                  <div class={styles.mask}></div>
                  <iframe
                    ref={staffDom}
                    class={styles.staff}
                    frameborder="0"
                    src={staffState.staffSrc}>
                  </iframe>
                </div>
              </div>
            }
          </div>
        </Sticky>
        <div class={styles.musicSection}>
          <div class={styles.avatarInfoBox}>
            <div class={styles.avatar}>
              <Image class={styles.userLogo} src={state.musicDetail.avatar} />
              <div class={styles.infoCon}>
                <div class={styles.info}>
                  <span class={styles.userName}>{state.musicDetail?.username}</span>
                  {state.musicDetail.vipFlag && (
                    <img src={iconMember} class={styles.iconMember} />
                  )}
                </div>
                <div class={styles.sub}>
                  {state.musicDetail.subjectName}{' '}
                  {getGradeCh(state.musicDetail.currentGradeNum - 1)}
                </div>
              </div>
            </div>
            <div class={styles.linkes}>
              <img src={iconZan} class={styles.iconZan} />
              <span>{state.musicDetail.likeNum}</span>
            </div>
          </div>
          <TextEllipsis class={styles.textEllipsis} rows={2} content={state.musicDetail?.desc} expand-text="展开" collapse-text="收起" />
        </div>

        <div class={styles.likeSection}>
          <div class={styles.likeTitle}>点赞记录</div>
          {state.listState.dataShow ? (
            <List
              finished={state.listState.finished}
              finishedText=" "
              onLoad={getStarList}
              immediateCheck={false}>
              {state.list.map((item: any, index: number) => (
                <Cell
                  class={[styles.likeItem, index===state.list.length-1&&styles.likeItemLast]}
                  border={false}
                >
                  {{
                    icon: () => (
                      <Image src={item.userAvatar} class={styles.userLogo} />
                    ),
                    title: () => (
                      <div class={styles.userInfo}>
                        <p class={styles.name}>{item.userName}</p>
                        <p class={styles.sub}>
                          {item.subjectName}{' '}
                          {getGradeCh(item.currentGradeNum - 1)}
                        </p>
                      </div>
                    ),
                    value: () => (
                      <div class={styles.time}>
                        {dayjs(item.createTime).format('YYYY-MM-DD HH:mm')}
                      </div>
                    )
                  }}
                </Cell>
              ))}
            </List>
          ) : (
            <MEmpty class={styles.mEmpty} image={"empty2"} description="暂无点赞记录" />
          )}
        </div>
        {
          !isScreenScroll.value &&
          <MSticky ref={mStickyUpward} position="bottom" offsetBottom={state.heightB - 1 + "px"} >
            <div class={styles.upward}>
              <img src={iconUpward} />
            </div>
          </MSticky>
        }
        <MSticky ref={mStickyBottom} position="bottom" onBarHeight={(height: any) => {
            console.log(height, 'height', height)
            state.heightB = height
        }}>
          <div class={styles.bottomSection}>
            <div class={styles.bottomShare}>
              <p onClick={onDownload}>
                <img src={iconDownload} />
                <span>下载</span>
              </p>
              <p onClick={() => (state.shareStatus = true)}>
                <img src={iconShare} />
                <span>分享</span>
              </p>
              <p onClick={() => (state.deleteStatus = true)}>
                <img src={iconDelete} />
                <span>删除</span>
              </p>
            </div>
            <img src={iconEdit}
              class={styles.btnEdit}
              onClick={() => {
                router.push({
                  path: '/creation-edit',
                  query: {
                    id: state.id
                  }
                });
              }}
            />
          </div>
        </MSticky>

        <Popup
          v-model:show={state.deleteStatus}
          overlay-style={
            {
              backgroundColor:"rgba(0,0,0,.5)"
            }
          }
          round
          class={styles.popupContainer}>
            <img class={styles.prompt} src={promptImg} />
            <div class={styles.deleteBox}>
              <p class={styles.popupContent}>确定删除吗？</p>
              <div class={styles.popupBtnGroup}>
                <img src={canceImg} onClick={() => (state.deleteStatus = false)} />
                <img src={confirmImg} onClick={onDelete} />
              </div>
            </div>
        </Popup>

        <Popup
          position="bottom"
          v-model:show={state.shareStatus}
          style={{ background: 'transparent' }}>
          <ShareModel
            playType={state.playType}
            musicDetail={state.musicDetail}
            onClose={() => (state.shareStatus = false)}
          />
        </Popup>
        {
          !staffState.isShow && <Loading></Loading>
        }
      </div>
    );
  }
});
