<?php

namespace Doom\Picture;

use InvalidArgumentException;
use RuntimeException;

final class DoomPalette
{
    private const DEFAULT_HEX =
        '0000001f170b170f074b4b4bffffff1b1b1b1313130b0b0b0707072f371f232b0f171f070f17004f3b2b4733233f2b1b' .
        'ffb7b7f7ababf3a3a3eb9797e78f8fdf8787db7b7bd37373cb6b6bc76363bf5b5bbb5757b34f4faf4747a73f3fa33b3b' .
        '9b3333972f2f8f2b2b8b2323831f1f7f1b1b7717177313136b0f0f670b0b5f07075b07075307074f0000470000430000' .
        'ffebdfffe3d3ffdbc7ffd3bbffcfb3ffc7a7ffbf9bffbb93ffb383f7ab7befa373e79b6bdf9363d78b5bcf8353cb7f4f' .
        'bf7b4bb37347ab6f43a36b3f9b633b8f5f378757337f532f774f2b6b47275f4323533f1f4b371b3f2f17332b132b230f' .
        'efefefe7e7e7dfdfdfdbdbdbd3d3d3cbcbcbc7c7c7bfbfbfb7b7b7b3b3b3abababa7a7a79f9f9f9797979393938b8b8b' .
        '8383837f7f7f7777776f6f6f6b6b6b6363635b5b5b5757574f4f4f4747474343433b3b3b3737372f2f2f272727232323' .
        '77ff6f6fef6767df5f5fcf575bbf4f53af474b9f3f4393373f832f37732b2f632327531b1f431717330f13230b0b1707' .
        'bfa78fb79f87af977fa78f779f876f9b7f6b937b638b735b836b577b634f775f4b6f574367533f5f4b37574333533f2f' .
        '9f83638f7753836b4b775f3f6753335b472b4f3b2343331b7b7f636f7357676b4f5b634753573b474f333f472b373f27' .
        'ffff73ebdb57d7bb43c39b2faf7b1f9b5b13874307732b00ffffffffdbdbffbbbbff9b9bff7b7bff5f5fff3f3fff1f1f' .
        'ff0000ef0000e30000d70000cb0000bf0000b30000a700009b00008b00007f00007300006700005b00004f0000430000' .
        'e7e7ffc7c7ffababff8f8fff7373ff5353ff3737ff1b1bff0000ff0000e30000cb0000b300009b00008300006b000053' .
        'ffffffffebdbffd7bbffc79bffb37bffa35bff8f3bff7f1bf37317eb6f0fdf670fd75f0bcb5707c34f00b74700af4300' .
        'ffffffffffd7ffffb3ffff8fffff6bffff47ffff23ffff00a73f009f3700932f008723004f3b27432f1b3723132f1b0b' .
        '00005300004700003b00002f00002300001700000b000000ff9f43ffe74bff7bffff00ffcf00cf9f009b6f006ba76b6b';

    private static ?Palette $default = null;

    public static function default(): Palette
    {
        if (self::$default === null) {
            $bytes = hex2bin(self::DEFAULT_HEX);
            if ($bytes === false) {
                throw new RuntimeException('Failed to decode default palette bytes.');
            }

            self::$default = Palette::fromBytes($bytes);
        }

        return self::$default;
    }

    public static function fromPlaypal(string $playpalData, int $paletteIndex = 0): Palette
    {
        if ($paletteIndex < 0) {
            throw new InvalidArgumentException('Palette index must be >= 0.');
        }

        $offset = $paletteIndex * Palette::PALETTE_BYTES;
        if (strlen($playpalData) < ($offset + Palette::PALETTE_BYTES)) {
            throw new RuntimeException('PLAYPAL data does not include requested palette index.');
        }

        $paletteBytes = substr($playpalData, $offset, Palette::PALETTE_BYTES);

        return Palette::fromBytes($paletteBytes);
    }
}
