import { BoundingBox } from "./BoundingBox.js";

export class SelectionRenderer {
  constructor({ canvas, context, drawStroke }) {
    this.canvas = canvas;
    this.ctx = context;
    this.drawStroke = drawStroke;
    this.dashOffset = 0;
    this.animationFrame = null;
    this.activeLasso = null;
  }

  resizeToElement(element) {
    const rect = element.getBoundingClientRect();
    const ratio = window.devicePixelRatio || 1;
    const width = Math.max(1, rect.width, element.offsetWidth);
    const height = Math.max(1, rect.height, element.offsetHeight);
    this.canvas.width = Math.max(1, Math.round(width * ratio));
    this.canvas.height = Math.max(1, Math.round(height * ratio));
    this.canvas.style.width = `${width}px`;
    this.canvas.style.height = `${height}px`;
    this.ctx.setTransform(ratio, 0, 0, ratio, 0, 0);
  }

  clear() {
    this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
  }

  renderLasso(points) {
    this.activeLasso = points;
    if (!this.animationFrame) {
      this.#animateLasso();
    }
  }

  stopLasso() {
    this.activeLasso = null;
    if (this.animationFrame) {
      window.cancelAnimationFrame(this.animationFrame);
      this.animationFrame = null;
    }
  }

  renderSelection({ bounds, handles = true, toolbarAnchor = null } = {}) {
    this.stopLasso();
    this.clear();

    if (!BoundingBox.isValid(bounds)) {
      return;
    }

    const rect = BoundingBox.toRect(bounds);
    this.ctx.save();
    this.ctx.strokeStyle = "#6d38f0";
    this.ctx.lineWidth = 1.5;
    this.ctx.setLineDash([6, 4]);
    this.ctx.strokeRect(rect.x - 4, rect.y - 4, rect.width + 8, rect.height + 8);
    this.ctx.setLineDash([]);

    if (handles) {
      this.#drawHandles(rect);
      this.#drawRotationHandle(rect);
    }

    if (toolbarAnchor) {
      this.#drawToolbarAnchor(toolbarAnchor);
    }

    this.ctx.restore();
  }

  renderDragPreview(strokes, dx, dy, bounds) {
    this.clear();
    this.ctx.save();
    this.ctx.translate(dx, dy);
    strokes.forEach((stroke) => this.drawStroke(stroke, this.ctx));
    this.ctx.restore();

    if (BoundingBox.isValid(bounds)) {
      this.#drawSelectionBounds({
        minX: bounds.minX + dx,
        minY: bounds.minY + dy,
        maxX: bounds.maxX + dx,
        maxY: bounds.maxY + dy
      });
    }
  }

  #animateLasso() {
    this.clear();
    const points = this.activeLasso || [];
    if (points.length > 1) {
      this.ctx.save();
      this.ctx.strokeStyle = "#111827";
      this.ctx.lineWidth = 1.4;
      this.ctx.setLineDash([7, 5]);
      this.ctx.lineDashOffset = -this.dashOffset;
      this.ctx.beginPath();
      this.ctx.moveTo(points[0].x, points[0].y);
      points.slice(1).forEach((point) => this.ctx.lineTo(point.x, point.y));
      this.ctx.stroke();
      this.ctx.restore();
      this.dashOffset = (this.dashOffset + 0.8) % 12;
    }

    this.animationFrame = window.requestAnimationFrame(() => this.#animateLasso());
  }

  #drawHandles(rect) {
    const size = 8;
    const half = size / 2;
    const handles = [
      [rect.x, rect.y],
      [rect.x + rect.width / 2, rect.y],
      [rect.x + rect.width, rect.y],
      [rect.x + rect.width, rect.y + rect.height / 2],
      [rect.x + rect.width, rect.y + rect.height],
      [rect.x + rect.width / 2, rect.y + rect.height],
      [rect.x, rect.y + rect.height],
      [rect.x, rect.y + rect.height / 2]
    ];

    this.ctx.fillStyle = "#ffffff";
    this.ctx.strokeStyle = "#6d38f0";
    this.ctx.lineWidth = 1.5;
    handles.forEach(([x, y]) => {
      this.ctx.fillRect(x - half, y - half, size, size);
      this.ctx.strokeRect(x - half, y - half, size, size);
    });
  }

  #drawSelectionBounds(bounds) {
    const rect = BoundingBox.toRect(bounds);
    this.ctx.save();
    this.ctx.strokeStyle = "#6d38f0";
    this.ctx.lineWidth = 1.5;
    this.ctx.setLineDash([6, 4]);
    this.ctx.strokeRect(rect.x - 4, rect.y - 4, rect.width + 8, rect.height + 8);
    this.ctx.setLineDash([]);
    this.#drawHandles(rect);
    this.#drawRotationHandle(rect);
    this.ctx.restore();
  }

  #drawRotationHandle(rect) {
    const x = rect.x + rect.width / 2;
    const y = rect.y - 28;
    this.ctx.beginPath();
    this.ctx.moveTo(x, rect.y - 4);
    this.ctx.lineTo(x, y + 7);
    this.ctx.stroke();
    this.ctx.beginPath();
    this.ctx.arc(x, y, 7, 0, Math.PI * 2);
    this.ctx.fillStyle = "#ffffff";
    this.ctx.fill();
    this.ctx.stroke();
  }

  #drawToolbarAnchor(anchor) {
    this.ctx.fillStyle = "rgba(109, 56, 240, 0.18)";
    this.ctx.beginPath();
    this.ctx.arc(anchor.x, anchor.y, 3, 0, Math.PI * 2);
    this.ctx.fill();
  }
}
