<template>
  <div ref="svgDraw" id="konva-container" style="height: 100%"></div>
</template>

<script>
function base64ToBlob(base64) {
  const byteCharacters = atob(base64);
  const byteArrays = [];

  for (let offset = 0; offset < byteCharacters.length; offset += 512) {
    const slice = byteCharacters.slice(offset, offset + 512);
    const byteNumbers = new Array(slice.length);
    for (let i = 0; i < slice.length; i++) {
      byteNumbers[i] = slice.charCodeAt(i);
    }
    const byteArray = new Uint8Array(byteNumbers);
    byteArrays.push(byteArray);
  }
  return new Blob(byteArrays, { type: 'application/pdf' });
}

function createObjectURL(blob) {
  return URL.createObjectURL(blob);
}

function downloadPDF(base64, fileName) {
  const blob = base64ToBlob(base64);
  const url = createObjectURL(blob);
  const link = document.createElement('a');
  link.href = url;
  link.download = fileName || 'downloaded_pdf.pdf'; // 设置下载文件名，如果没有提供文件名，则默认为'downloaded_pdf.pdf'
  document.body.appendChild(link); // 添加到DOM树中以便触发下载
  link.click(); // 模拟点击下载
  document.body.removeChild(link); // 下载完成后移除元素
  URL.revokeObjectURL(url); // 释放URL对象
}
import Konva from 'konva';
import DxfParser from 'dxf-parser';
import jsPDF from 'jspdf';
import { formatEntity, handleFn, centering } from './components/entityFormatting';
var konvaStage = null,
  konvaLayer = null;
var recordLayerConfig = {};
var activedSvgPan = {
  x: 0,
  y: 0,
  zoom: {
    x: 1,
    y: 1,
  },
};
export default {
  name: 'Fl2dcanvas',
  components: {},
  data() {
    return {
      bounds: null,
    };
  },
  created() {
    //resize方法
    window.addEventListener('resize', () => {
      if (konvaStage) {
        const obj = document.getElementById('konva-container');
        konvaStage.setWidth(obj.clientWidth);
        konvaStage.setHeight(obj.clientHeight);
        konvaStage._resizeDOM();
      }
    });

    this.$nextTick(() => {
      console.log(document.getElementById('konva-container'));
      console.log(this.$refs.svgDraw);
      konvaStage = new Konva.Stage({
        className: 'stage',
        container: 'konva-container',
        width: this.$refs.svgDraw.clientWidth,
        height: this.$refs.svgDraw.clientHeight,
        draggable: true,
      });
      //init layer
      konvaLayer = new Konva.Layer({
        name: 'konva-layer',
        x: 0,
        y: 0,
      });
      //设置清晰度
      konvaLayer.getCanvas().setPixelRatio(2);
      konvaStage.add(konvaLayer);
      konvaLayer.draw();
      var scaleBy = 1.1;
      //初始化缩放方法
      konvaStage.on('wheel', e => {
        console.log(e);
        e.evt.preventDefault();
        var oldScale = konvaStage.scaleX();
        var pointer = konvaStage.getPointerPosition();
        var mousePointTo = {
          x: (pointer.x - konvaStage.x()) / oldScale,
          y: (pointer.y - konvaStage.y()) / oldScale,
        };
        // how to scale? Zoom in? Or zoom out?
        let direction = e.evt.deltaY > 0 ? -1 : 1;
        if (e.evt.ctrlKey) {
          direction = -direction;
        }
        var newScale = direction > 0 ? oldScale * scaleBy : oldScale / scaleBy;
        this.scaleRatio = Math.ceil(newScale);
        console.log(this.scaleRatio);
        // 判断比例尺百分比
        console.log(this.scaleRatio);
        if (this.scaleRatio < 1 || this.scaleRatio >= 100) return;
        // 设置放大缩小多少倍
        konvaStage.scale({ x: newScale, y: newScale });
        var newPos = {
          x: pointer.x - mousePointTo.x * newScale,
          y: pointer.y - mousePointTo.y * newScale,
        };
        konvaStage.position(newPos);
      });
      konvaStage.on('pointerdblclick', e => {
        konvaStage.scale({
          x: 1,
          y: 1,
        });
        let x = -parseFloat(this.bounds.minX);
        let y = -parseFloat(this.bounds.minY);

        konvaStage.setX(x);
        konvaStage.setY(y); // 750

        //算一下舞台中点
        let width = konvaStage.width();
        let height = konvaStage.height();
        let x1 = width / 2;
        let y1 = height / 2;

        //算包围盒宽高

        let boundsWidth = this.bounds.maxX - this.bounds.minX;
        let boundsHeight = Math.abs(Math.abs(this.bounds.maxY) - Math.abs(this.bounds.minY));

        let x2 = x + x1 - boundsWidth / 2;
        let y2 = y + y1 - boundsHeight / 2;

        konvaStage.setX(x2);
        konvaStage.setY(y2); // 750
      });
    });

    //create方法结束
  },
  //销毁方法

  methods: {
    updateBounds(v) {
      if (this.bounds === null) {
        this.bounds = { minX: v.x, maxX: v.x, minY: v.y, maxY: v.y };
      } else {
        if (v.x < this.bounds.minX) {
          this.bounds.minX = v.x;
        } else if (v.x > this.bounds.maxX) {
          this.bounds.maxX = v.x;
        }
        if (v.y < this.bounds.minY) {
          this.bounds.minY = v.y;
        } else if (v.y > this.bounds.maxY) {
          this.bounds.maxY = v.y;
        }
      }
    },
    //思路是计算居中包围盒，然后排除脏数据。
    loadDxf(data) {
      let _this = this;

      /* if(this.layer!=null){
                      let nodes=this.layer.find(".item");
                      for(let i=0;i<nodes.length;i++){
                        nodes[i].destroy();
                      }
                    }*/

      konvaLayer.destroyChildren();
      const parser = new DxfParser();
      let dxf = parser.parse(data);
      let entities = formatEntity(dxf.entities);

      let layers = dxf.tables.layer.layers;
      //加载图纸
      console.log(dxf);
      console.log(entities);

      for (let key in entities) {
        if (entities[key]) {
          let group = [];
          let l = entities[key].length;
          let layerConfig = recordLayerConfig[key];
          let configParams =
            layerConfig && Object.keys(layerConfig).length > 0 ? layerConfig : null;
          for (let i = 0; i < l; i++) {
            let type = entities[key][i].type;
            handleFn(
              type,
              dxf,
              entities[key][i],
              group,
              key,
              configParams,
              konvaLayer,
              recordLayerConfig
            );
          }
          if (!konvaLayer) return;
          for (let i = 0; i < group.length; i++) {
            let entity = group[i];
            if (entity.type === 'text') {
              if (konvaLayer) konvaLayer.add(entity.obj);
            }
          }

          if (group[0].stroke == undefined) {
            console.log(group);
            group[0].stroke = '#000';
          }
          let customShape = new Konva.Shape({
            x: 0,
            y: 0,
            strokeWidth: 0.2,
            name: key.replace(/\s*/g, ''),
            entityId: key,
            stroke: group[0].stroke,
            customColor: configParams ? configParams.color : '',
            //visible: configParams ? configParams.visible :true,
            sceneFunc(context, shape) {
              context.beginPath();
              for (let i = 0; i < group.length; i++) {
                let entity = group[i];

                if (entity.type === 'line') {
                  context.strokeStyle = entity.stroke;
                  let x1 = entity.x1;
                  let y1 = entity.y1;
                  let x2 = entity.x2;
                  let y2 = entity.y2;
                  if (x1 != undefined && y1 != undefined && x2 != undefined && y2 != undefined) {
                    context.moveTo(x1, -parseFloat(y1));
                    context.lineTo(x2, -parseFloat(y2));
                  }
                  let v1 = {};
                  v1.x = x1;
                  v1.y = y1;
                  let v2 = {};
                  v2.x = x2;
                  v2.y = y2;
                  _this.updateBounds(v1);
                  _this.updateBounds(v2);
                }
                if (entity.type === 'polyline') {
                  context.strokeStyle = entity.stroke;

                  let flag = false;

                  let points = entity.points;

                  let closed = entity.closed;

                  for (let j = 0; j < points.length; j++) {
                    let index = j % 2;
                    if (index === 0) {
                      let x = points[j];
                      let y = points[j + 1];
                      let point = {};
                      point.x = x;
                      point.y = y;
                      _this.updateBounds(point);

                      if (j === 0) {
                        context.moveTo(x, y);
                      } else {
                        context.lineTo(x, y);
                      }
                    }

                    if (closed) {
                      if (j === points.length - 1) {
                        context.lineTo(points[0], points[1]);
                      }
                    }
                  }
                }
              }
              // context.closePath();
              context.fillStrokeShape(shape);
            },
          });
          if (konvaLayer) konvaLayer.add(customShape);
        }
      }
      //缩放视口
      let scale = 1;
      const boundingRect = konvaLayer.getClientRect();
      let ratio = Number((this.$refs.svgDraw?.clientWidth / boundingRect.width).toFixed(1));
      if (ratio > 2) {
        scale = Number((boundingRect.width / boundingRect.height).toFixed(1));
        scale = scale < 2 ? 2 : scale;
      }
      // konvaStage.scale({
      //  x: scale,
      // y: scale,
      //})
      const boundingScale = konvaLayer.getClientRect();
      //平移视口
      const x =
        this.$refs.svgDraw?.clientWidth / 2 -
        (Math.ceil(boundingScale.width) / 2 + boundingScale.x / 2);
      const y =
        this.$refs.svgDraw.clientHeight / 2 -
        (Math.ceil(boundingScale.height) / 2 + boundingScale.y);

      konvaStage.scale({
        x: 2,
        y: 2,
      });
      konvaStage.setX(0);
      konvaStage.setY(750); // 750

      activedSvgPan.zoom.x = 0;
      activedSvgPan.zoom.y = 750;
      activedSvgPan.x = x;
      activedSvgPan.y = x;
      setTimeout(() => {
        this.$emit('loaded');
      }, 100);
    },
    toPdf(name) {
      //konvaStage.scale({
      //x: activedSvgPan.zoom.x,
      //y: activedSvgPan.zoom.y,
      //});
      //konvaStage.setX(activedSvgPan.x);
      //konvaStage.setY(activedSvgPan.y);
      // get data URL with default settings

      // open in new window
      konvaLayer.getCanvas().setPixelRatio(2);
      const jpegURL = konvaStage.toDataURL({
        mimeType: 'image/jpeg',
        quality: 1,
        pixelRatio: 2,
      });

      let pageData = konvaLayer.canvas.toDataURL('image/jpeg', 2);

      let img = new Image();
      img.src = jpegURL;
      const pdf = new jsPDF('l', 'px', [konvaStage.width(), konvaStage.height()]);

      pdf.addImage(
        konvaStage.toDataURL({ pixelRatio: 2 }),
        0,
        0,
        konvaStage.width(),
        konvaStage.height()
      );

      pdf.save(name + '.pdf');
      // var imgData = canvas.toDataURL('image/png');
      //doc.text("Hello world!", 10, 10);
      //doc.save("a4.pdf");
    },
    toPdfs(list) {
      let _this = this;
      const pdf = new jsPDF('l', 'px', [konvaStage.width(), konvaStage.height()]);
      const exportPixelRatio = 2; // 可以 2/3/4 自己调

      for (let i = 0; i < list.length; i++) {
        let data = list[i];
        //先绘制图面
        konvaLayer.destroyChildren();
        const parser = new DxfParser();
        let dxf = parser.parse(data);
        let entities = formatEntity(dxf.entities);
        let layers = dxf.tables.layer.layers;
        for (let key in entities) {
          if (entities[key]) {
            let group = [];
            let l = entities[key].length;
            let layerConfig = recordLayerConfig[key];
            let configParams =
              layerConfig && Object.keys(layerConfig).length > 0 ? layerConfig : null;
            for (let i = 0; i < l; i++) {
              let type = entities[key][i].type;
              handleFn(
                type,
                dxf,
                entities[key][i],
                group,
                key,
                configParams,
                konvaLayer,
                recordLayerConfig
              );
            }
            if (!konvaLayer) return;
            for (let i = 0; i < group.length; i++) {
              let entity = group[i];
              if (entity.type === 'text') {
                if (konvaLayer) konvaLayer.add(entity.obj);
              }
            }

            if (group[0].stroke == undefined) {
              console.log(group);
              group[0].stroke = '#000';
            }
            let customShape = new Konva.Shape({
              x: 0,
              y: 0,
              strokeWidth: 0.2,
              name: key.replace(/\s*/g, ''),
              entityId: key,
              stroke: group[0].stroke,
              customColor: configParams ? configParams.color : '',
              //visible: configParams ? configParams.visible :true,
              sceneFunc(context, shape) {
                context.beginPath();
                for (let i = 0; i < group.length; i++) {
                  let entity = group[i];

                  if (entity.type === 'line') {
                    context.strokeStyle = entity.stroke;
                    let x1 = entity.x1;
                    let y1 = entity.y1;
                    let x2 = entity.x2;
                    let y2 = entity.y2;
                    if (x1 != undefined && y1 != undefined && x2 != undefined && y2 != undefined) {
                      context.moveTo(x1, -parseFloat(y1));
                      context.lineTo(x2, -parseFloat(y2));
                    }
                    let v1 = {};
                    v1.x = x1;
                    v1.y = y1;
                    let v2 = {};
                    v2.x = x2;
                    v2.y = y2;
                    _this.updateBounds(v1);
                    _this.updateBounds(v2);
                  }
                  if (entity.type === 'polyline') {
                    context.strokeStyle = entity.stroke;

                    let flag = false;

                    let points = entity.points;
                    let closed = entity.closed;

                    for (let j = 0; j < points.length; j++) {
                      let index = j % 2;
                      if (index === 0) {
                        let x = points[j];
                        let y = points[j + 1];

                        let point = {};
                        point.x = x;
                        point.y = y;
                        _this.updateBounds(point);

                        if (j === 0) {
                          context.moveTo(x, y);
                        } else {
                          context.lineTo(x, y);
                        }
                      }

                      if (closed) {
                        if (j === points.length - 1) {
                          context.lineTo(points[0], points[1]);
                        }
                      }
                    }
                  }
                }
                // context.closePath();
                context.fillStrokeShape(shape);
              },
            });
            if (konvaLayer) konvaLayer.add(customShape);
          }
        }
        konvaStage.scale({
          x: 2,
          y: 2,
        });

        konvaStage.setX(0);
        konvaStage.setY(750); // 750
        //添加成功移动视口位置

        if (i == 0) {
          pdf.addImage(
            konvaStage.toDataURL({ pixelRatio: 2 }),
            0,
            0,
            konvaStage.width(),
            konvaStage.height()
          );
        } else {
          pdf.addPage();
          pdf.addImage(
            konvaStage.toDataURL({ pixelRatio: 2 }),
            0,
            0,
            konvaStage.width(),
            konvaStage.height()
          );
        }
      }

      pdf.save('批量导出.pdf');

      // var imgData = canvas.toDataURL('image/png');
      //doc.text("Hello world!", 10, 10);
      //doc.save("a4.pdf");
    },
    clearCache() {
      konvaLayer && konvaLayer.destroyChildren();
      konvaLayer && konvaLayer.destroy();
      konvaLayer && konvaLayer.clear();
      konvaStage && konvaStage.destroy();
      konvaStage && konvaStage.clearCache();
      konvaLayer = null;
      konvaStage = null;
    },
    beforeDestroy() {
      this.clearCache();
    },
  },
};
</script>
<style lang="scss" scoped>
#konva-container {
  z-index: 3;
  width: 100%;
  height: 100%;
  cursor: pointer;
  overflow: hidden;
}
</style>
