<?php

namespace Doom\Texture;

use Doom\Wad\File;
use RuntimeException;

final class TextureResolver
{
    private function __construct(private readonly File $wad)
    {
    }

    public static function forWad(File $wad): self
    {
        return new self($wad);
    }

    /**
     * @param string[] $textureLumpNames
     * @return array<string, ResolvedTexture>
     */
    public function resolveAll(array $textureLumpNames = ['TEXTURE1', 'TEXTURE2']): array
    {
        $pNames = $this->wad->pNames();
        if ($pNames === null) {
            throw new RuntimeException('Missing PNAMES lump.');
        }

        $resolved = [];

        foreach ($textureLumpNames as $textureLumpName) {
            $textureX = $this->wad->firstTextureXByName($textureLumpName);
            if ($textureX === null) {
                continue;
            }

            foreach ($textureX->textures as $texture) {
                $resolved[$texture->name] = $this->resolveTexture($texture, $pNames);
            }
        }

        return $resolved;
    }

    public function resolveByName(string $textureName, array $textureLumpNames = ['TEXTURE1', 'TEXTURE2']): ?ResolvedTexture
    {
        $textureName = strtoupper($textureName);
        $resolved = $this->resolveAll($textureLumpNames);

        return $resolved[$textureName] ?? null;
    }

    /**
     * @param string[] $pNames
     */
    private function resolveTexture(TextureDefinition $texture, array $pNames): ResolvedTexture
    {
        $patches = [];

        foreach ($texture->patches as $patch) {
            $patchName = $pNames[$patch->patch] ?? null;
            $patchLump = $patchName === null ? null : $this->wad->firstLumpByName($patchName);

            $patches[] = new ResolvedTexturePatch(
                originX: $patch->originX,
                originY: $patch->originY,
                patchIndex: $patch->patch,
                patchName: $patchName,
                stepDir: $patch->stepDir,
                colorMap: $patch->colorMap,
                lumpIndex: $patchLump?->index,
            );
        }

        return new ResolvedTexture(
            name: $texture->name,
            masked: $texture->masked,
            width: $texture->width,
            height: $texture->height,
            patches: $patches,
        );
    }
}
