<?php

namespace App\Services\PlanDigitizer;

/**
 * Flattened vector content of a page, kept in parallel arrays because a plan
 * routinely holds hundreds of thousands of segments.
 */
class VectorContent
{
    /** @var list<float> four entries per segment: x1, y1, x2, y2 */
    public array $coordinates = [];

    /** @var list<int> layer index per segment */
    public array $segmentLayers = [];

    /** @var list<int> colour index per segment */
    public array $segmentColors = [];

    /** @var list<float> stroke width per segment, in page units */
    public array $segmentWidths = [];

    /** @var list<array{points: list<float>, layer: int, color: int, closed: bool}> */
    public array $fills = [];

    /** @var list<string> layer names, indexed by layer id */
    public array $layers = [''];

    /** @var list<array{0: float, 1: float, 2: float}> RGB 0..1 triplets, indexed by colour id */
    public array $colors = [];

    /** @var list<array{text: string, x: float, y: float, size: float}> */
    public array $texts = [];

    public function segmentCount(): int
    {
        return count($this->segmentLayers);
    }

    public function layerIndex(string $name): int
    {
        $index = array_search($name, $this->layers, true);

        if ($index === false) {
            $this->layers[] = $name;

            return count($this->layers) - 1;
        }

        return (int) $index;
    }

    /** @return array<string, int> segment count per layer name */
    public function layerHistogram(): array
    {
        $counts = [];

        foreach ($this->segmentLayers as $layer) {
            $name = $this->layers[$layer] ?? '';
            $counts[$name] = ($counts[$name] ?? 0) + 1;
        }

        arsort($counts);

        return $counts;
    }

    /** @return array<string, int> segment count per `r,g,b` key */
    public function colorHistogram(): array
    {
        $counts = [];

        foreach ($this->segmentColors as $color) {
            $key = self::colorKey($this->colors[$color] ?? [0.0, 0.0, 0.0]);
            $counts[$key] = ($counts[$key] ?? 0) + 1;
        }

        arsort($counts);

        return $counts;
    }

    /** @param array{0: float, 1: float, 2: float} $rgb */
    public static function colorKey(array $rgb): string
    {
        return implode(',', array_map(
            static fn (float $channel): int => (int) round(max(0.0, min(1.0, $channel)) * 255),
            $rgb,
        ));
    }
}
