import useResizeAware from '../../../../../../../hooks/useResizeAware';
import bus from '../../../../../../../utils/bus';
import { formatHMSHover } from '../../../../../../../utils/misc';
import { Tooltip } from '@tingwu/design';
import { useCallback, useEffect, useRef, useState } from 'react';
import styled from 'styled-components';
import { CHANGESEEK, POINTTIMEINFOVISIBLE } from '../AudioController';
import './index.less';

export const CHANGECOVERWIDTH = 'tingwu2_change_cover_width';

const Cover = styled.div`
  position: absolute;
  height: 100%;
  background-color: rgba(255, 255, 255, 0.3);
`;

interface AudioWaveProps {
  audioData: number[];
  percent: number;
  duration: number;
  markSegData: any[];
  tips?: Array<{
    startTime: number;
    percent: number;
    title: string;
    content: string;
    color: string;
  }>;
}

// 渐进色
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const gradient: Array<[number, string]> = [
  [0, 'rgb(241, 239, 255)'],
  [0.1, 'rgb(219, 225, 255)'],
  [0.2, 'rgb(147, 159, 251)'],
  [0.3, 'rgb(200, 166, 255)'],
  [0.5, 'rgb(219, 213, 255)'],
  [0.7, 'rgb(187, 195, 255)'],
  [0.8, 'rgb(200, 166, 255)'],
  [0.9, 'rgb(219, 225, 255)'],
  [1, 'rgb(235, 231, 255)'],
];

// mark颜色
// const markColors = ['#FFBA10', '#00A6FF', '#FF0077'];

const AudioWave = (props: AudioWaveProps) => {
  const {
    audioData,
    duration,
    percent: leftPercent,
    tips = [],
    markSegData,
  } = props;
  // 音频数据比例转化
  const maxAuionData = Math.max(...audioData);
  const audioProportionData = audioData.map(
    (data) => Math.abs(data) / maxAuionData,
  );

  const containerRef = useRef<HTMLDivElement | null>(null);
  const svgRef = useRef<SVGSVGElement | null>(null);
  const [svgWidth, setSvgWidth] = useState(0);
  const [svgHeight, setSvgHeight] = useState(0);
  const [drawData, setDraData] = useState<string>('');
  const [resizeListener, sizes]: any = useResizeAware();
  const [coverWidth, setWidth] = useState('0%');

  const widthCacheRef = useRef<number>();
  const heightCacheRef = useRef<number>();
  const audioProportionDataCacheRef = useRef<string>();

  const init = () => {
    if (!containerRef.current || !svgRef.current) return;
    const { width, height } = containerRef.current.getBoundingClientRect();
    setSvgWidth(width);
    setSvgHeight(height);
  };

  const computeDrawData = useCallback(() => {
    if (!containerRef.current) return;
    // 获取画板宽高
    const { width, height } = containerRef.current.getBoundingClientRect();
    const audioProportionDataStr = JSON.stringify(audioProportionData);
    const { length } = audioProportionData;
    if (
      width === widthCacheRef.current &&
      height === heightCacheRef.current &&
      audioProportionDataStr === audioProportionDataCacheRef.current
    ) {
      return;
    }

    widthCacheRef.current = width;
    heightCacheRef.current = height;
    audioProportionDataCacheRef.current = audioProportionDataStr;

    // 处理音频数据
    const drawStep = width / length;
    const waveData = audioProportionData.reduce(
      (result: Array<{ x: number; y: number }>, _, index, array) => {
        // 整段音频数据切分段，取每段最大数据作为曲线数据
        const partNum = width / 20;
        const partLength = Math.round(length / partNum);
        if (index % partLength === 0) {
          const partIndex = Math.floor(index / partLength);
          const part = array.slice(
            partIndex * partLength,
            (partIndex + 1) * partLength,
          );
          const maxData = Math.max(...part); // 冗余计算
          const maxIndex: any =
            Number(part.findIndex((item) => item === maxData)) +
            partIndex * partLength;

          return [
            ...result,
            {
              x: drawStep * maxIndex,
              y: (1 - maxData) * height,
            },
          ];
        }
        return result;
      },
      [],
    );

    // 移到波形起点
    let data = `M${0} ${waveData[0]?.y}`;
    // 计算曲线数据
    for (let i = 0; i < waveData.length - 2; i++) {
      const control = waveData[i + 1];
      const endData = waveData[i + 2];
      const end = {
        x: (control.x + endData.x) / 2,
        y: (control.y + endData.y) / 2,
      };
      data += ` Q${control.x} ${control.y} ${end.x} ${end.y}`;
    }
    // 闭合图形
    data += ` T${width} ${(1 - audioProportionData[length - 1]) * height}`;
    data += ` L${width} ${height}`;
    data += ` L${0} ${height}`;

    setDraData(data);
  }, [audioProportionData]);

  useEffect(() => {
    // 初始化svg宽高
    init();
    // 计算波形图轮廓曲线数据
    computeDrawData();
  }, [computeDrawData, sizes]);

  const changeTargetTime = (e: any) => {
    const rect = e.currentTarget.getBoundingClientRect();
    let offsetX = e.clientX - rect.left;
    // const offsetY = e.clientY - rect.top;
    if (offsetX < 0) {
      offsetX = 0;
    }
    const currentTimeArg = (offsetX / rect.width) * duration;
    const time = formatHMSHover(Number(currentTimeArg.toFixed(0)));
    bus.emit(POINTTIMEINFOVISIBLE, {
      time,
      text: '',
      offsetX,
      rectWidth: rect.width,
    });
  };

  const clearTargetTime = () => {
    bus.emit(POINTTIMEINFOVISIBLE, {});
  };

  const changeCurrent = (e: any) => {
    const rect = e.currentTarget.getBoundingClientRect();
    const offsetX = e.clientX - rect.left;
    const currentTimeArg = (offsetX / rect.width) * duration;
    // onClickCbk(parseInt('' + currentTimeArg))
    bus.emit(CHANGESEEK, currentTimeArg);
  };

  useEffect(() => {
    if (markSegData.length > 0) {
      setWidth(`calc(${100 - leftPercent}% - 2px)`);
    } else {
      setWidth(`calc(${100 - leftPercent}%)`);
    }
  }, [leftPercent, markSegData]);

  useEffect(() => {
    bus.on(CHANGECOVERWIDTH, onCoverChange);
    return () => {
      bus.on(CHANGECOVERWIDTH, onCoverChange);
    };
  }, []);

  const onCoverChange = (width: string) => {
    setWidth(width);
  };

  return (
    <div
      ref={containerRef}
      className={'audio-wave'}
      onMouseEnter={changeTargetTime}
      onMouseMove={changeTargetTime}
      onMouseLeave={clearTargetTime}
      onClick={changeCurrent}
    >
      {/* 监听容器宽高 */}
      {resizeListener}
      {/* 音频波形轮廓图 */}
      <Cover
        style={{
          width: coverWidth,
          right: 0,
        }}
      />
      <svg
        ref={svgRef}
        viewBox={`0 0 ${svgWidth} ${svgHeight}`}
        width={svgWidth}
        height={svgHeight}
      >
        {/* <defs>
          <linearGradient id={'gradient'}>
            {gradient.map(([offset, stopColor]) => (
              <stop key={offset} offset={offset} stopColor={stopColor} />
            ))}
          </linearGradient>
        </defs> */}
        <path d={drawData} fill="#DCDBFF" />
      </svg>

      {/* 标记气泡tip */}
      {tips?.map(({ percent, title, content, color }) => (
        <Tooltip
          key={percent}
          color={'#27264D'}
          overlayClassName={'audio-wave-tooltip'}
          overlay={
            <>
              <div
                style={{
                  color: 'rgba(255, 255, 255,.6)',
                  transform: 'scale(0.8)',
                  transformOrigin: 'left',
                }}
              >
                {title}
              </div>
              <div className="arrow" />
              <div title={content}>
                {content.length > 15
                  ? `${content.slice(0, 15)}...`
                  : content || ''}
              </div>
            </>
          }
          getPopupContainer={(triggerNode) => triggerNode.parentElement as any}
        >
          <span
            className={'audio-wave-mark'}
            onMouseEnter={(e) => {
              e.stopPropagation();
              clearTargetTime();
            }}
            onMouseMove={(e) => {
              e.stopPropagation();
              clearTargetTime();
            }}
            style={{
              left: `${percent}%`,
              backgroundColor: color,
            }}
            // onClick={() => {
            //   // onClickCbk(parseInt(startTime.toFixed(0)))
            // }}
          />
        </Tooltip>
      ))}
    </div>
  );
};

export default AudioWave;
