<?php

namespace App\Services\PlanDigitizer;

/**
 * Maps PDF user space (y up, origin at the media box corner) to the pixel space
 * shared by the rasterized base plan, the lot polygons and the SVG viewBox.
 */
class PlanFrame
{
    public function __construct(
        public readonly float $originX,
        public readonly float $originY,
        public readonly float $pageWidth,
        public readonly float $pageHeight,
        public readonly float $scale,
        public readonly int $width,
        public readonly int $height,
    ) {}

    /** Builds a frame whose longest edge lands close to `$targetEdge` pixels. */
    public static function fit(PdfPage $page, int $targetEdge = 3600): self
    {
        $pageWidth = max(1.0, $page->width());
        $pageHeight = max(1.0, $page->height());
        $scale = $targetEdge / max($pageWidth, $pageHeight);

        return new self(
            originX: $page->originX(),
            originY: $page->originY(),
            pageWidth: $pageWidth,
            pageHeight: $pageHeight,
            scale: $scale,
            width: (int) round($pageWidth * $scale),
            height: (int) round($pageHeight * $scale),
        );
    }

    public function toPixelX(float $x): float
    {
        return ($x - $this->originX) * $this->scale;
    }

    public function toPixelY(float $y): float
    {
        return ($this->pageHeight - ($y - $this->originY)) * $this->scale;
    }

    /**
     * @param  list<array{0: float, 1: float}>  $ring
     * @return list<array{0: float, 1: float}>
     */
    public function ringToPixels(array $ring): array
    {
        return array_map(
            fn (array $point): array => [
                round($this->toPixelX($point[0]), 2),
                round($this->toPixelY($point[1]), 2),
            ],
            $ring,
        );
    }
}
