<?php

declare(strict_types=1);

namespace App\Domain\QrCode\Pattern;

use App\Domain\QrCode\ValueObject\Position;

class AlignmentPattern implements PatternInterface
{
    // Tabelle der Ausrichtungsmuster-Positionen für Versionen 1-40
    private const POSITIONS = [
        1 => [],
        2 => [6, 18],
        3 => [6, 22],
        4 => [6, 26],
        5 => [6, 30],
        6 => [6, 34],
        7 => [6, 22, 38],
        8 => [6, 24, 42],
        9 => [6, 26, 46],
        10 => [6, 28, 50],
        // ... weitere Versionen hier hinzufügen
    ];

    public function __construct(
        private readonly int $version
    ) {
    }

    public function apply(array &$matrix, int $size): void
    {
        if ($this->version === 1) {
            return; // Version 1 hat keine Ausrichtungsmuster
        }

        $positions = self::POSITIONS[$this->version] ?? $this->calculatePositions($size);

        foreach ($positions as $centerRow) {
            foreach ($positions as $centerCol) {
                if ($this->overlapsWithFinderPattern($centerRow, $centerCol, $size)) {
                    continue;
                }

                $this->applyPattern($matrix, $centerRow, $centerCol, $size);
            }
        }
    }

    private function applyPattern(array &$matrix, int $centerRow, int $centerCol, int $size): void
    {
        // 5x5 Ausrichtungsmuster
        for ($r = -2; $r <= 2; $r++) {
            for ($c = -2; $c <= 2; $c++) {
                $position = new Position($centerRow + $r, $centerCol + $c);

                if ($position->isWithinBounds($size)) {
                    // Äußerer Rand oder Mittelpunkt
                    $isBlack = abs($r) === 2 || abs($c) === 2 || ($r === 0 && $c === 0);
                    $matrix[$centerRow + $r][$centerCol + $c] = $isBlack;
                }
            }
        }
    }

    private function overlapsWithFinderPattern(int $row, int $col, int $size): bool
    {
        return ($row <= 8 && $col <= 8) ||
               ($row <= 8 && $col >= $size - 9) ||
               ($row >= $size - 9 && $col <= 8);
    }

    private function calculatePositions(int $size): array
    {
        // Vereinfachte Berechnung für fehlende Versionen
        $positions = [6];

        if ($size >= 25) { // Ab Version 2
            $positions[] = $size - 7;
        }

        return $positions;
    }
}
