<?php

declare(strict_types=1);

namespace App\Domain\QrCode\Service;

use App\Domain\QrCode\ValueObject\GaloisField;
use App\Domain\QrCode\ValueObject\Polynomial;

/**
 * Reed-Solomon Encoder für QR-Code-Fehlerkorrektur
 */
class ReedSolomonEncoder
{
    private GaloisField $field;

    public function __construct()
    {
        $this->field = new GaloisField();
    }

    /**
     * Kodiert die Daten mit Reed-Solomon-Fehlerkorrektur
     *
     * @param array $data Daten als Array von Bytes
     * @param int $eccLength Anzahl der Error-Correction-Codewords
     * @return array Kodierte Daten mit ECC-Bytes
     */
    public function encode(array $data, int $eccLength): array
    {
        if ($eccLength === 0) {
            return $data;
        }

        // Erzeuge das Generator-Polynom für die gegebene Anzahl von ECC-Bytes
        $generator = Polynomial::buildGenerator($this->field, $eccLength);

        // Konvertiere Daten in ein Polynom
        $dataPolynomial = new Polynomial($this->field, $data);

        // Multipliziere mit x^eccLength, um Platz für ECC-Bytes zu schaffen
        $paddedData = array_merge(
            array_fill(0, $eccLength, 0),
            $dataPolynomial->getCoefficients()
        );
        $paddedPolynomial = new Polynomial($this->field, $paddedData);

        // Dividiere durch das Generator-Polynom, der Rest ist der ECC
        $divResult = $paddedPolynomial->divideAndRemainder($generator);
        $remainder = $divResult['remainder']->getCoefficients();

        // Fülle den Rest mit Nullen auf, falls er zu kurz ist
        if (count($remainder) < $eccLength) {
            $remainder = array_merge(
                array_fill(0, $eccLength - count($remainder), 0),
                $remainder
            );
        }

        // Konkateniere Daten und ECC-Bytes
        return array_merge($data, $remainder);
    }
}
