<template>
  <div class="rectangle-zoom-container" ref="containerRef"></div>
</template>

<script>
import { ref, onMounted, onUnmounted, watch } from 'vue';

export default {
  name: 'RectangleZoom',
  props: {
    viewer: {
      type: Object,
      required: true
    },
    enabled: {
      type: Boolean,
      default: true
    },
    lineColor: {
      type: String,
      default: '#00aaff'
    },
    fillColor: {
      type: String,
      default: 'rgba(0, 170, 255, 0.2)'
    },
    lineWidth: {
      type: Number,
      default: 2
    },
    minSize: {
      type: Number,
      default: 10
    }
  },
  setup(props) {
    const containerRef = ref(null);
    let canvas = null;
    let ctx = null;
    let isDrawing = false;
    let isShiftDown = false;
    let startX = 0;
    let startY = 0;
    let currentX = 0;
    let currentY = 0;

    const initCanvas = () => {
      if (!props.viewer || !props.viewer.container) return;
      
      const container = props.viewer.container;
      
      const existingCanvas = document.getElementById('rectangle-zoom-canvas');
      if (existingCanvas) {
        existingCanvas.parentNode.removeChild(existingCanvas);
      }
      
      canvas = document.createElement('canvas');
      canvas.id = 'rectangle-zoom-canvas';
      canvas.style.position = 'absolute';
      canvas.style.top = '0';
      canvas.style.left = '0';
      canvas.style.width = '100%';
      canvas.style.height = '100%';
      canvas.style.pointerEvents = 'none';
      canvas.style.zIndex = '1000';
      container.appendChild(canvas);
      
      ctx = canvas.getContext('2d');
      resizeCanvas();
    };

    const resizeCanvas = () => {
      if (!canvas || !props.viewer || !props.viewer.container) return;
      const rect = props.viewer.container.getBoundingClientRect();
      canvas.width = rect.width;
      canvas.height = rect.height;
    };

    const drawRectangle = () => {
      if (!ctx) return;
      
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      
      if (!isDrawing) return;
      
      const x = Math.min(startX, currentX);
      const y = Math.min(startY, currentY);
      const width = Math.abs(currentX - startX);
      const height = Math.abs(currentY - startY);
      
      ctx.beginPath();
      ctx.strokeStyle = props.lineColor;
      ctx.lineWidth = props.lineWidth;
      ctx.setLineDash([8, 4]);
      ctx.strokeRect(x, y, width, height);
      
      ctx.fillStyle = props.fillColor;
      ctx.fillRect(x, y, width, height);
      
      ctx.setLineDash([]);
    };

    const getRectangleExtent = () => {
      if (!props.viewer || !props.viewer.scene || !props.viewer.scene.globe) return null;

      const x1 = Math.min(startX, currentX);
      const y1 = Math.min(startY, currentY);
      const x2 = Math.max(startX, currentX);
      const y2 = Math.max(startY, currentY);

      const scene = props.viewer.scene;
      const camera = props.viewer.camera;
      const globe = scene.globe;

      const corners = [
        [x1, y1], [x2, y1], [x2, y2], [x1, y2]
      ];

      let lons = [];
      let lats = [];

      for (const [cx, cy] of corners) {
        const ray = camera.getPickRay(new Cesium.Cartesian2(cx, cy));
        if (!ray) continue;

        let cartesian;
        if (globe) {
          cartesian = globe.pick(ray, scene);
        }
        if (!cartesian) {
          cartesian = camera.pickEllipsoid(new Cesium.Cartesian2(cx, cy), Cesium.Ellipsoid.WGS84);
        }
        if (!cartesian) continue;

        const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
        lons.push(cartographic.longitude);
        lats.push(cartographic.latitude);
      }

      if (lons.length === 0) return null;

      return {
        west: Math.min(...lons),
        east: Math.max(...lons),
        south: Math.min(...lats),
        north: Math.max(...lats)
      };
    };

    const flyToExtent = (extent) => {
      if (!extent || !props.viewer) return;

      const rectangle = Cesium.Rectangle.fromRadians(
        extent.west, extent.south, extent.east, extent.north
      );

      props.viewer.camera.flyTo({
        destination: rectangle,
        duration: 1.0,
        easingFunction: Cesium.EasingFunction.QUADRATIC_IN_OUT
      });
    };

    const setCanvasCapture = (capture) => {
      if (!canvas) return;
      canvas.style.pointerEvents = capture ? 'auto' : 'none';
    };

    const setCursor = (cursor) => {
      if (canvas) {
        canvas.style.cursor = cursor;
      }
      if (!props.viewer) return;
      if (props.viewer.container) {
        props.viewer.container.style.cursor = cursor;
      }
      if (props.viewer.scene && props.viewer.scene.canvas) {
        props.viewer.scene.canvas.style.cursor = cursor;
      }
    };

    const clearCursorOverride = () => {
      if (canvas) {
        canvas.style.cursor = '';
      }
      if (!props.viewer) return;
      if (props.viewer.container) {
        props.viewer.container.style.cursor = '';
      }
      if (props.viewer.scene && props.viewer.scene.canvas) {
        props.viewer.scene.canvas.style.cursor = '';
      }
    };

    const getCanvasPos = (clientX, clientY) => {
      if (!canvas) return null;
      const rect = canvas.getBoundingClientRect();
      return new Cesium.Cartesian2(clientX - rect.left, clientY - rect.top);
    };

    const handleMouseDown = (event) => {
      if (!props.enabled) return;
      if (event.button !== 0) return;
      if (!isShiftDown) return;

      const pos = getCanvasPos(event.clientX, event.clientY);
      if (!pos) return;

      startX = pos.x;
      startY = pos.y;
      currentX = pos.x;
      currentY = pos.y;
      isDrawing = true;
    };

    const handleMouseMove = (event) => {
      if (!isDrawing) return;

      const pos = getCanvasPos(event.clientX, event.clientY);
      if (!pos) return;

      currentX = pos.x;
      currentY = pos.y;

      drawRectangle();
    };

    const endDrawing = () => {
      if (!isDrawing) return;
      if (!ctx) return;

      const width = Math.abs(currentX - startX);
      const height = Math.abs(currentY - startY);

      if (width >= props.minSize && height >= props.minSize) {
        const extent = getRectangleExtent();
        if (extent) {
          flyToExtent(extent);
        }
      }

      ctx.clearRect(0, 0, canvas.width, canvas.height);
      isDrawing = false;
    };

    const handleMouseUp = (event) => {
      if (!isDrawing) return;
      if (event.button !== 0) return;

      const pos = getCanvasPos(event.clientX, event.clientY);
      if (pos) {
        currentX = pos.x;
        currentY = pos.y;
      }

      endDrawing();
    };

    const handleKeyDown = (event) => {
      if (event.key === 'Shift' || event.key === 'ShiftLeft' || event.key === 'ShiftRight') {
        isShiftDown = true;
        setCanvasCapture(true);
        setCursor('crosshair');
      }
    };

    const handleKeyUp = (event) => {
      if (event.key === 'Shift' || event.key === 'ShiftLeft' || event.key === 'ShiftRight') {
        isShiftDown = false;
        endDrawing();
        setCanvasCapture(false);
        clearCursorOverride();
      }
    };

    const addEventListeners = () => {
      if (!canvas) return;

      canvas.addEventListener('mousedown', handleMouseDown);
      canvas.addEventListener('mousemove', handleMouseMove);
      canvas.addEventListener('mouseup', handleMouseUp);
      canvas.addEventListener('mouseleave', endDrawing);
      window.addEventListener('mouseup', handleMouseUp);

      window.addEventListener('keydown', handleKeyDown);
      window.addEventListener('keyup', handleKeyUp);
      window.addEventListener('resize', resizeCanvas);
    };

    const removeEventListeners = () => {
      if (canvas) {
        canvas.removeEventListener('mousedown', handleMouseDown);
        canvas.removeEventListener('mousemove', handleMouseMove);
        canvas.removeEventListener('mouseup', handleMouseUp);
        canvas.removeEventListener('mouseleave', endDrawing);
      }

      window.removeEventListener('mouseup', handleMouseUp);
      window.removeEventListener('keydown', handleKeyDown);
      window.removeEventListener('keyup', handleKeyUp);
      window.removeEventListener('resize', resizeCanvas);
    };

    const destroyCanvas = () => {
      if (canvas && canvas.parentNode) {
        canvas.parentNode.removeChild(canvas);
        canvas = null;
        ctx = null;
      }
    };

    onMounted(() => {
      if (props.enabled) {
        initCanvas();
        addEventListeners();
      }
    });

    onUnmounted(() => {
      removeEventListeners();
      destroyCanvas();
    });

    watch(() => props.enabled, (newVal) => {
      if (newVal) {
        initCanvas();
        addEventListeners();
      } else {
        removeEventListeners();
        destroyCanvas();
      }
    });

    return {
      containerRef
    };
  }
};
</script>

<style scoped>
.rectangle-zoom-container {
  display: none;
}
</style>
