import { memo } from 'react';
import { Group, Rect } from 'react-konva';
import type { Point } from '@house-plan-maker/shared';

interface SelectionLayerProps {
  readonly zoom: number;
  readonly panOffset: Point;
  /** Bounding box in world coordinates of current selection. */
  readonly selectionBox: {
    x: number;
    y: number;
    width: number;
    height: number;
  } | null;
  /** Drag selection rectangle in world coordinates (while dragging). */
  readonly dragRect: {
    x: number;
    y: number;
    width: number;
    height: number;
  } | null;
}

const SELECTION_STROKE = '#4c6ef5';
const SELECTION_FILL = 'rgba(76, 110, 245, 0.08)';
const DRAG_RECT_STROKE = '#4c6ef5';
const DRAG_RECT_FILL = 'rgba(76, 110, 245, 0.1)';
/** Padding around selection box in meters. */
const PADDING = 0.05;

export const SelectionLayer = memo(function SelectionLayer({
  zoom,
  panOffset,
  selectionBox,
  dragRect,
}: SelectionLayerProps) {
  return (
    <Group listening={false}>
      {/* Selection bounding box with resize handles */}
      {selectionBox && (
        <SelectionBoundingBox
          box={selectionBox}
          zoom={zoom}
          panOffset={panOffset}
        />
      )}

      {/* Drag selection rectangle */}
      {dragRect && (
        <DragSelectionRect
          rect={dragRect}
          zoom={zoom}
          panOffset={panOffset}
        />
      )}
    </Group>
  );
});

interface SelectionBoundingBoxProps {
  readonly box: { x: number; y: number; width: number; height: number };
  readonly zoom: number;
  readonly panOffset: Point;
}

function SelectionBoundingBox({ box, zoom, panOffset }: SelectionBoundingBoxProps) {
  const x = (box.x - PADDING) * zoom + panOffset.x;
  const y = (box.y - PADDING) * zoom + panOffset.y;
  const w = (box.width + PADDING * 2) * zoom;
  const h = (box.height + PADDING * 2) * zoom;

  return (
    <>
      {/* Dashed bounding rectangle */}
      <Rect
        x={x}
        y={y}
        width={w}
        height={h}
        stroke={SELECTION_STROKE}
        strokeWidth={1}
        dash={[4, 4]}
        fill={SELECTION_FILL}
        listening={false}
      />
    </>
  );
}

interface DragSelectionRectProps {
  readonly rect: { x: number; y: number; width: number; height: number };
  readonly zoom: number;
  readonly panOffset: Point;
}

function DragSelectionRect({ rect, zoom, panOffset }: DragSelectionRectProps) {
  const x = rect.x * zoom + panOffset.x;
  const y = rect.y * zoom + panOffset.y;
  const w = rect.width * zoom;
  const h = rect.height * zoom;

  return (
    <Rect
      x={x}
      y={y}
      width={w}
      height={h}
      stroke={DRAG_RECT_STROKE}
      strokeWidth={1}
      dash={[6, 3]}
      fill={DRAG_RECT_FILL}
      listening={false}
    />
  );
}
