<template>
  <div>
    <div class="canvas-box solid" ref="canvasBox">
      <img :src="background" style="
          width: 100%;
          height: 100%;
          position: absolute;
          top: 0;
          left: 0;
          object-fit: fill;
        " v-show="background != null" />
      <!--用来和鼠标进行交互操作的canvas-->
      <canvas id="canvasTool"></canvas>
      <!--存储已生成的点线，避免被清空-->
      <canvas id="canvasSave" @click="handleCanvasSaveClick" @mousemove="handleCanvasSaveMove"></canvas>
      <div style="width: 100%; height: 100%; position: absolute; top: 0; left: 0" v-show="open && single"></div>
    </div>
  </div>
</template>

<script setup>
import { nextTick, onMounted, defineEmits, onActivated } from "vue";

const emit = defineEmits(["finish"]);
const { proxy } = getCurrentInstance();

const props = defineProps({
  single: Boolean, // 是否单个图形，目前只支持单个图形
  background: String, // 背景图
  limit: Number, // 闲置边数
  points: {
    type: Array,
    default: () => []
  }
});
const { single, limit, points } = toRefs(props);
watch(
  points,
  (newValue) => {
	points.value = newValue;
	points.value.map(item => {
		handleCanvasSaveClick(item)
	})
	if(points.value.length){
		saveCanvas(); //生成画
	}
  },
  { deep: true }
);
const open = ref(false);
const lineColor = "rgba(64, 158, 255, 1)";
var can;
var ctx;
var canSave;
var ctxSave;

var pointX, pointY;
var pointArr = []; //存放坐标的数组

var oIndex = -1; //判断鼠标是否移动到起始点处，-1为否，1为是
const coincidentDistance = 10; // 重合距离

function initCanvas() {
  can = document.getElementById("canvasTool");
  can.width = proxy.$refs["canvasBox"].clientWidth;
  can.height = proxy.$refs["canvasBox"].clientHeight;
  // console.log(can.width, can.height);
  ctx = can.getContext("2d");
  ctx.strokeStyle = lineColor; //线条颜色
  ctx.fillStyle = "rgba(64, 158, 255,0.1)"; //填充颜色
  ctx.lineWidth = 4; //线条粗细
  ctx.globalAlpha = 0.7; //半透明

  canSave = document.getElementById("canvasSave");
  //------------这里报错---------
  canSave.width = proxy.$refs["canvasBox"].clientWidth;
  canSave.height = proxy.$refs["canvasBox"].clientHeight;
  ctxSave = canSave.getContext("2d");
  ctxSave.strokeStyle = lineColor; //线条颜色
  ctxSave.fillStyle = "rgba(64, 158, 255,0.1)"; //填充颜色
  ctxSave.lineWidth = 4; //线条粗细
  ctxSave.globalAlpha = 0.7; //半透明
  // console.log(can);
  // console.log(canSave);
  // console.log(points)
  // console.log(points.value)
}

function handleCanvasSaveClick(e) {
  // console.log(e);
  if (limit.value != null) {
    if (pointArr.length > limit.value) {
      proxy.$modal.msgError(`最多设置【${limit.value}】个点`);
      return;
    }
  }

  if (e.layerX) {
    pointX = e.offsetX == undefined ? e.layerX : e.offsetX;
    pointY = e.offsetY == undefined ? e.layerY : e.offsetY;
    // pointX = e.layerX;
    // pointY = e.layerY;

    var piX, piY;
    if (oIndex > 0 && pointArr.length > 0) {
      console.log("aaaaaaaaaaaaaa");
      piX = pointArr[0].x;
      piY = pointArr[0].y;
      //画点
      makearc(ctx, piX, piY, GetRandomNum(2, 2), 0, 180, lineColor);
      pointArr.push({ x: piX, y: piY });
      if (isExistIntersection()) {
        proxy.$modal.msgError(`存在交叉线段，请重新绘制`);
        revoke();
        return;
      }
      canvasSave(pointArr); //保存点线同步到另一个canvas
      saveCanvas(); //生成画布
    } else {
      console.log("bbbbbbbbbbbbb");

      piX = pointX;
      piY = pointY;
      makearc(ctx, piX, piY, GetRandomNum(2, 2), 0, 180, lineColor);
      pointArr.push({ x: piX, y: piY });
      if (isExistIntersection()) {
        proxy.$modal.msgError(`存在交叉线段，请重新绘制`);
        revoke();
        return;
      }
      canvasSave(pointArr); //保存点线同步到另一个canvas
    }
  }
}

function handleCanvasSaveMove(e) {
  // console.log(e);

  if (e.offsetX || e.layerX) {
    pointX = e.offsetX == undefined ? e.layerX : e.offsetX;
    pointY = e.offsetY == undefined ? e.layerY : e.offsetY;
    // pointX = e.layerX;
    // pointY = e.layerY;
    var piX, piY;
    /*清空画布*/
    // console.log(ctx);
    ctx.clearRect(0, 0, can.width, can.height);
    /*鼠标下跟随的圆点*/
    makearc(ctx, pointX, pointY, GetRandomNum(4, 4), 0, 180, lineColor);

    if (pointArr.length > 0) {
      if (
        pointX > pointArr[0].x - coincidentDistance &&
        pointX < pointArr[0].x + coincidentDistance &&
        pointY > pointArr[0].y - coincidentDistance &&
        pointY < pointArr[0].y + coincidentDistance
      ) {
        if (pointArr.length > 1) {
          piX = pointArr[0].x;
          piY = pointArr[0].y;
          // console.log(piX, piY);

          ctx.clearRect(0, 0, can.width, can.height);
          makearc(ctx, piX, piY, GetRandomNum(4, 4), 0, 180, lineColor);
          oIndex = 1;
        }
      } else {
        piX = pointX;
        piY = pointY;
        oIndex = -1;
      }
      /*开始绘制*/
      ctx.beginPath();
      ctx.moveTo(pointArr[0].x, pointArr[0].y);
      if (pointArr.length > 1) {
        for (var i = 1; i < pointArr.length; i++) {
          ctx.lineTo(pointArr[i].x, pointArr[i].y);
        }
      }
      ctx.lineTo(piX, piY);
      ctx.fillStyle = "rgba(161,195,255,1)"; //填充颜色
      ctx.fill(); //填充
      ctx.stroke(); //绘制
    }
  }
}

// 存储已生成的点线
function canvasSave(pointArr) {
  // console.log(isExistIntersection());
  ctxSave.clearRect(0, 0, ctxSave.width, ctxSave.height);
  ctxSave.beginPath();
  if (pointArr.length > 1) {
    ctxSave.moveTo(pointArr[0].x, pointArr[0].y);
    for (var i = 1; i < pointArr.length; i++) {
      ctxSave.lineTo(pointArr[i].x, pointArr[i].y);
      ctxSave.fillStyle = "rgba(161,195,255,1)"; //填充颜色
      //ctxSave.fill();
      ctxSave.stroke(); //绘制
    }
    ctxSave.closePath();
  }
}

/*生成画布 结束绘画*/
function saveCanvas() {
  if (pointArr.length < 3) {
    proxy.$modal.msgError(`检查区域至少为三边形，请重新绘制`);
    revoke();
    return;
  }
  ctx.clearRect(0, 0, can.width, can.height);
  ctxSave.closePath(); //结束路径状态，结束当前路径，如果是一个未封闭的图形，会自动将首尾相连封闭起来
  ctxSave.fill(); //填充
  ctxSave.stroke(); //绘制
  // console.log(pointArr);
  // console.log(isExistIntersection());
  if (single.value) {
    open.value = true;
  }
  emit("finish", pointArr.slice(1));
  pointArr = [];
}

/*验证canvas画布是否为空函数*/
function isCanvasBlank(canvas) {
  var blank = document.createElement("canvas"); //创建一个空canvas对象
  blank.width = canvas.width;
  blank.height = canvas.height;
  return canvas.toDataURL() == blank.toDataURL(); //为空 返回true
}

/*canvas生成圆点*/
function GetRandomNum(Min, Max) {
  var Range = Max - Min;
  var Rand = Math.random();
  return Min + Math.round(Rand * Range);
}

function makearc(ctx, x, y, r, s, e, color) {
  ctx.clearRect(0, 0, 199, 202); //清空画布
  ctx.beginPath();
  ctx.fillStyle = color;
  ctx.arc(x, y, r, s, e);
  ctx.fill();
}

function reset() {
  ctx.clearRect(0, 0, can.width, can.height);
  ctxSave.clearRect(0, 0, canSave.width, canSave.height);
  pointArr = [];
  open.value = false;
}

// 撤销上一步
function revoke() {
  if (open.value && single.value) {
    reset();
  }
  ctx.clearRect(0, 0, can.width, can.height);
  ctxSave.clearRect(0, 0, canSave.width, canSave.height);
  pointArr.pop();
  pointArr.map((item) => {
    let _e = {
      layerX: item.x,
      layerY: item.y,
    };
    handleCanvasSaveMove(_e);
  });
}

function isExistIntersection() {
  let result = false;
  for (let i = 0; i < pointArr.length - 1; i++) {
    let a = pointArr[i];
    let b = pointArr[i + 1];
    for (let j = 0; j < pointArr.length - 1; j++) {
      if (i == j) {
        continue;
      }
      let c = pointArr[j];
      let d = pointArr[j + 1];
      result = isIntersection(a, b, c, d);
      if (result) {
        return result;
      }
      // console.log(result)
    }
  }
  return result;
}

//判断两个线段是否相交
function isIntersection(a, b, c, d) {
  /** 1 解线性方程组, 求线段交点. **/
  // 如果分母为0 则平行或共线, 不相交
  var denominator = (b.y - a.y) * (d.x - c.x) - (a.x - b.x) * (c.y - d.y);
  if (denominator == 0) {
    return false;
  }

  // 线段所在直线的交点坐标 (x , y)
  var x =
    ((b.x - a.x) * (d.x - c.x) * (c.y - a.y) +
      (b.y - a.y) * (d.x - c.x) * a.x -
      (d.y - c.y) * (b.x - a.x) * c.x) /
    denominator;
  var y =
    -(
      (b.y - a.y) * (d.y - c.y) * (c.x - a.x) +
      (b.x - a.x) * (d.y - c.y) * a.y -
      (d.x - c.x) * (b.y - a.y) * c.y
    ) / denominator;

  /** 2 判断交点是否在两条线段上 **/
  if (
    // 交点在线段1上
    (x - a.x) * (x - b.x) < 0 &&
    (y - a.y) * (y - b.y) < 0 &&
    // 且交点也在线段2上
    (x - c.x) * (x - d.x) < 0 &&
    (y - c.y) * (y - d.y) < 0
  ) {
    // // 返回交点p
    // return {
    //   x: x,
    //   y: y,
    // };
    return true;
  }
  //否则不相交
  return false;
}

onMounted(() => {
  nextTick(() => {
    initCanvas();
  });
});

// onActivated(() => {
//   console.log("onActivated");
//   nextTick(() => {
//     initCanvas();
//   });
// })



defineExpose({
  reset,
  revoke,
  initCanvas,
});
</script>

<style lang="scss" scoped>
.canvas-box {
  position: relative;
  width: 100%;
  height: 100%;

  >canvas {
    position: absolute;
    top: 0;
    left: 0;
    width: 960px;
    height: 540px;
    // width: 100%;
    // height: 100%;
  }
}
</style>