<script lang="ts" setup>
import { nextTick, onMounted, onUpdated, ref, watch } from 'vue';
import html2canvas from 'html2canvas';
import JSMpeg from '@cycjimmy/jsmpeg-player';
import { useMessage } from 'naive-ui';
import type { UploadFileInfo } from 'naive-ui';
import { Camera, Images } from '@vicons/ionicons5';
import { ArrowReset24Filled } from '@vicons/fluent';
import { CleaningServicesOutlined } from '@vicons/material';
import { DrawPolygon } from '@vicons/fa';
import { HandMove } from '@vicons/tabler';
import { extend } from 'dayjs';
import { api_base64ToWebURl } from '@/api/index';

/** 清空 handleCleanDrawNode 撤销 handleResetDraw 绘制 getClickDrawInfo 平移 handleTranslationDraw */

/**
 * 问题
 *
 * 1. 视频监控临时测试
 * 2.
 */

interface IElementNode {
  x: string | number;
  y: string | number;
}

interface IEventTarget {
  offsetX?: string;
  offsetY?: string;
  [key: string]: any;
}

interface ICanvasStyle {
  strokeStyle: string;
  lineWidth: number;
}

const openType = ref(true);
const dialogSpin = ref(false);
const imgUrl = ref('');
const message = useMessage();
const el = ref<HTMLElement | null>(null);

interface IDrawProp {
  callback: (val: string) => void;
  val: string;
  iamge: string;
  imgCallback: (val: string) => void;
}

const props = defineProps({
  callback: {
    type: Function,
    require: true
  },
  val: {
    type: String,
    require: true
  },
  imgCallback: {
    type: Function,
    require: true
  },
  image: {
    type: String,
    require: true
  }
});

// 绘图提交
const handleSubmit = () => { };

// 节点记录
const elNodes = ref<IElementNode[]>([]);

const config = ref({
  width: 0,
  height: 0
});

// 配置信息
const canvasConfig = ref<ICanvasStyle>({
  strokeStyle: '#FF0000',
  lineWidth: 2
});

interface ICanvasElement extends Element {
  beginPath: (a1: number, a2: number) => void;
  moveTo: (a1: number | string, a2: number | string) => void;
  lineTo: (a1: number | string, a2: number | string) => void;
  stroke: () => void;
}

// 绘制函数
const handleCanvasDraw = () => {

  console.log('==================== handleCanvasDraw', elNodes.value.length);

  // 绘制线
  const drawLineFunc = (el: ICanvasElement, prev: IElementNode, next: IElementNode) => {
    el.globalCompositeOperation = 'source-over';
    el.beginPath(0, 0);

    // 移动到起始点
    el.moveTo(prev.x, prev.y);

    // 绘制一条线到终点
    el.lineTo(next.x, next.y);

    // 执行绘制
    el.stroke();
  };

  // 绘制点
  const drawMarkerFunc = (el: ICanvasElement, prev: IElementNode, next: IElementNode) => { };


  // 实际绘制
  const handleInfoToCanvas = () => {
    nextTick(() => {
      const ctx = el.value;
      //  动态传参
      // eslint-disable-next-line guard-for-in
      for (const style in canvasConfig.value) {
        ctx[style] = canvasConfig.value[style];
      }

      elNodes.value.reduce((prev, cur) => {
        // 画点
        drawMarkerFunc(ctx, prev, cur);

        // 画线
        drawLineFunc(ctx, prev, cur);

        return cur;
      });
    });
  };

  if (elNodes.value.length > 1) handleInfoToCanvas();
};

// 计算百分比
const autoComputePercentage = (): string => {
  // if (elNodes.value.length < 2) return ``;

  // eslint-disable-next-line no-underscore-dangle
  const _w = 1920;
  // eslint-disable-next-line no-underscore-dangle
  const _h = 1080;

  // eslint-disable-next-line no-underscore-dangle
  let _str = ``;

  const { width, height } = config.value;

  for (const info of elNodes.value) {
    _str += `(${(((info.x as number) / width) * _w).toFixed(0)},${(((info.y as number) / height) * _h).toFixed(0)}),`;
  }

  return _str.slice(0, _str.length - 1);
};

// 节点信息
const getCanvasNodeInfo = (e: IEventTarget): IElementNode => {

  const { offsetX, offsetY } = e;

  // eslint-disable-next-line no-underscore-dangle
  const info = {
    x: offsetX,
    y: offsetY
  } as IElementNode;

  // ================================ 闭合处理 | S
  /** 最终的一个点回到第一个点, 上下左右在 15 这个区间, 自动回归到原点[确保图形连贯] */

  const last = elNodes.value[0];

  if (elNodes.value.length > 2 && Math.abs(offsetX - last.x) < 15 && Math.abs(offsetY - last.y) < 15) {
    elNodes.value.push(last);
    return last;
  }

  // ================================ 闭合处理 | E
  elNodes.value.push(info);
  return info;
};

// 撤销
const handleResetDraw = () => {
  elNodes.value.pop();
  el.value.restore();
};


const handleClickCanvas = (e: Event) => {
  /** openType 多边形开始流程 getCanvasNodeInfo 返回当前点击的节点信息 handleCanvasDraw 绘制 handleSubmit 将组件信息传递给父组件 */
  if (!openType.value) return message.error('点击多边形后, 开始绘制!');

  if (!imgUrl.value) return message.error('请选择上传底图后, 开始绘制!');

  // 闭合后, 是否绘制.
  if (elNodes.value.length > 2) {
    // eslint-disable-next-line no-underscore-dangle
    const _f = elNodes.value[0];
    // eslint-disable-next-line no-underscore-dangle
    const _l = elNodes.value[elNodes.value.length - 1];
    if (_f.x === _l.x && _f.y === _l.y) return message.warning('绘制用图形已经闭合, 请返回上一步, 选择最终闭合节点!');
  }

  // 新节点
  getCanvasNodeInfo(e);

  // 绘制
  handleCanvasDraw();

  props.callback(autoComputePercentage());

  // 计算
  console.log(autoComputePercentage());
};

// 图片放上去
const startDrawImg = (callback?: () => void | undefined) => {
  nextTick(() => {
    const ctx = el.value;
    const img = new Image();
    img.src = imgUrl.value;
    img.onload = () => {
      ctx.drawImage(img, 0, 0, config.value.width, config.value.height); // 第一个参数是图片，第二个和第三个参数是坐标，第四和第五个参数是图片宽高或裁剪区域
      // setTimeout(() => {
      //   callback && callback();
      // })

      handleCanvasDraw()
    };
  });
};

// 清空
const handleCleanDrawNode = () => {
  elNodes.value = [];
  el.value?.reset();
  startDrawImg();
};


// 多边形
const handleOpenDraw = () => {
  openType.value = true;
};

// 上传图片
const handleUploadIMG = () => { };

// 视频截图 fempeg | rstp
const handleCaptureVideoImg = () => {
  nextTick(() => {
    html2canvas(document.getElementById('canvas-3') as HTMLElement)
      .then(canvas => {
        dialogSpin.value = false;
        api_base64ToWebURl(canvas.toDataURL('image/png')).then(res => {
          if (res.data.code === 200) {
            imgUrl.value = res.data.data;
            props?.imgCallback(res.data.data);
            message.success('截图抓取成功!');
            startDrawImg();
          }
        });
      })
      .catch(() => {
        dialogSpin.value = false;
      });
  });
};

// 初始化
const fempegVideoInit = () => {
  // 临时测试
  const rtsp1 = 'rtsp://admin:gemho10-7@192.168.0.56:554/h264/ch1/main/av_stream';
  // eslint-disable-next-line no-new
  new JSMpeg.Player(
    `ws://192.168.1.96:9999/rtsp?url=${btoa(rtsp1)}&scale=640:-1&-b:v=1k&brightness=0.2&saturation=1.8`,
    {
      canvas: document.getElementById('canvas-3'),
      preserveDrawingBuffer: true
    }
  );
};

// ======================= IMG 上传 | S
const beforeUpload = (data: { file: UploadFileInfo; fileList: UploadFileInfo[] }): boolean => {
  if (data.file.file?.type !== 'image/png') {
    message.error('只能上传png格式的图片文件，请重新上传');
    return false;
  }
  return true;
};

const handleFinish = ({ file, event }: { file: UploadFileInfo; event?: ProgressEvent }) => {
  const res = event?.target && event?.target?.response && JSON.parse(event?.target?.response);
  if (res.code === 200) {
    props?.imgCallback(res.data);
    imgUrl.value = res.data;
    startDrawImg();
    message.success('图片上传成功!');
  }
  return file;
};
// ======================= IMG 上传 | E

watch(elNodes, () => {
  handleCanvasDraw();
});

const getHeightOrWidth = () => {
  const canvasEl = document.getElementById('DrawCompoent');
  const canvasWrapEl = document.getElementById('DrawWrap');

  canvasEl.height = canvasWrapEl.scrollHeight;
  canvasEl.width = canvasWrapEl.scrollWidth;

  return {
    _canvas_el: canvasEl,
    _canvas_wrap_el: canvasWrapEl,
    _canvas_context: canvasEl.getContext('2d'),
    width: canvasWrapEl.scrollWidth,
    height: canvasWrapEl.scrollHeight
  };
};


// 暂存节点
const oldValue = [
  {
    x: 552,
    y: 436
  },
  {
    x: 478,
    y: 814
  },
  {
    x: 1822,
    y: 778
  },
  {
    x: 552,
    y: 436
  }
]

onMounted(() => {
  config.value.height = getHeightOrWidth().height;
  config.value.width = getHeightOrWidth().width;
  el.value = getHeightOrWidth()._canvas_context;
  // el.value?.reset();

  elNodes.value = oldValue;

  fempegVideoInit();


  // startDrawImg();

  // if (props.image) {
  //   imgUrl.value = props.image;
  //   startDrawImg(() => {
  //     elNodes.value = [
  //       {
  //         x: 751,
  //         y: 511
  //       },
  //       {
  //         x: 785,
  //         y: 684
  //       },
  //       {
  //         x: 1358,
  //         y: 598
  //       },
  //       {
  //         x: 751,
  //         y: 511
  //       }
  //     ];
  //     handleCanvasDraw();
  //   });
  // }

});


onUpdated(() => {
  fempegVideoInit();
});
</script>

<template>
  <!-- 抓图测试-->
  <div id="canvas-4">
    <canvas id="canvas-3"></canvas>
  </div>
  <!--  -->
  <NSpin :show="dialogSpin">
    <div>
      <!-- 工具栏 -->
      <div class="draw-tool">
        <div>
          <!-- DrawPolygon -->
          <div @click="handleOpenDraw">
            <div style="text-align: center">
              <NIcon size="26">
                <DrawPolygon />
              </NIcon>
              <br />
              <span style="display: inline-block">多边形</span>
            </div>
          </div>
          <!-- <div @click="translateDraw">
            <div style="text-align: center">
              <NIcon size="26">
                <HandMove />
              </NIcon>
              <br />
              <span style="display: inline-block">平移</span>
            </div>
          </div>
          <div @click="handleResetDraw">
            <div style="text-align: center">
              <NIcon size="26">
                <ArrowReset24Filled />
              </NIcon>
              <br />
              <span style="display: inline-block">撤销</span>
            </div>
          </div> -->
          <div @click="handleCleanDrawNode">
            <div style="text-align: center">
              <NIcon size="26">
                <CleaningServicesOutlined />
              </NIcon>
              <br />
              <span style="display: inline-block">清空</span>
            </div>
          </div>
        </div>
        <div>
          <div>
            <div style="text-align: center" @click="handleCaptureVideoImg">
              <NIcon size="26">
                <Camera />
              </NIcon>
              <br />
              <span style="display: inline-block">获取截图</span>
            </div>
          </div>
          <NUpload :max="1" action="/v1/common/upload" @before-upload="beforeUpload" @finish="handleFinish">
            <div style="text-align: center">
              <NIcon size="26">
                <Images />
              </NIcon>
              <br />
              <span style="display: inline-block">上传图片</span>
            </div>
          </NUpload>
        </div>
      </div>
      <!-- === -->
      <div id="DrawWrap">
        <canvas id="DrawCompoent" @click="handleClickCanvas"></canvas>
      </div>
    </div>
  </NSpin>
</template>

<style lang="scss" scoped>
#canvas-4 {
  position: fixed;
  top: -10000px;
}

#canvas-4>canvas {
  width: 600px;
  height: 350px;
}

.draw-tool {
  height: 70px !important;
  margin: 20px 0;
  display: flex;
  padding-top: 5px;
  justify-content: space-between;
  background: #f8f8f9;
  border-radius: 10px;

  &>div {
    display: flex;
    justify-content: start;
  }

  &>div>div {
    height: 100%;
    width: 80px;
    display: flex;
    justify-content: center;
    align-items: center;
    cursor: pointer;
    font-size: 14px;
  }
}

#DrawCompoent {
  height: 100%;
  width: 100%;
  background-color: #f8f8f9;
}

#DrawWrap {
  height: 300px;
  transition: calc(2);
  position: relative;
}
</style>
