package p.studio.workspaces.assets.messages;

import p.packer.dtos.PackerCodecConfigurationFieldDTO;
import p.packer.dtos.PackerDiagnosticDTO;
import p.packer.messages.assets.OutputCodecCatalog;
import p.packer.messages.assets.OutputFormatCatalog;
import p.studio.workspaces.assets.metadata.AssetStudioGlyphMaterialMetadata;
import p.studio.workspaces.assets.metadata.AssetStudioSceneBankMetadata;

import java.util.List;
import java.util.Map;
import java.util.Objects;

public record AssetWorkspaceAssetDetails(
        AssetWorkspaceAssetSummary summary,
        List<AssetWorkspaceAssetAction> actions,
        OutputFormatCatalog outputFormat,
        OutputCodecCatalog outputCodec,
        List<OutputCodecCatalog> availableOutputCodecs,
        Map<OutputCodecCatalog, List<PackerCodecConfigurationFieldDTO>> codecConfigurationFieldsByCodec,
        List<PackerCodecConfigurationFieldDTO> metadataFields,
        Map<String, Object> outputPipeline,
        AssetWorkspaceBankCompositionDetails bankComposition,
        List<Map<String, Object>> pipelinePalettes,
        AssetStudioGlyphMaterialMetadata glyphMaterialMetadata,
        AssetStudioSceneBankMetadata sceneBankMetadata,
        AssetWorkspaceSceneBankValidation sceneBankValidation,
        List<PackerDiagnosticDTO> diagnostics) {

    public AssetWorkspaceAssetDetails {
        Objects.requireNonNull(summary, "summary");
        actions = List.copyOf(Objects.requireNonNull(actions, "actions"));
        outputFormat = Objects.requireNonNullElse(outputFormat, OutputFormatCatalog.UNKNOWN);
        outputCodec = Objects.requireNonNullElse(outputCodec, OutputCodecCatalog.UNKNOWN);
        availableOutputCodecs = List.copyOf(Objects.requireNonNull(availableOutputCodecs, "availableOutputCodecs"));
        codecConfigurationFieldsByCodec = Map.copyOf(Objects.requireNonNull(codecConfigurationFieldsByCodec, "codecConfigurationFieldsByCodec"));
        metadataFields = List.copyOf(Objects.requireNonNull(metadataFields, "metadataFields"));
        outputPipeline = Map.copyOf(Objects.requireNonNull(outputPipeline, "outputPipeline"));
        bankComposition = Objects.requireNonNull(bankComposition, "bankComposition");
        pipelinePalettes = List.copyOf(Objects.requireNonNull(pipelinePalettes, "pipelinePalettes"));
        sceneBankValidation = Objects.requireNonNullElse(sceneBankValidation, AssetWorkspaceSceneBankValidation.NOT_APPLICABLE);
        diagnostics = List.copyOf(Objects.requireNonNull(diagnostics, "diagnostics"));
    }

    public AssetWorkspaceAssetDetails withBankComposition(AssetWorkspaceBankCompositionDetails bankComposition) {
        return new AssetWorkspaceAssetDetails(
                summary,
                actions,
                outputFormat,
                outputCodec,
                availableOutputCodecs,
                codecConfigurationFieldsByCodec,
                metadataFields,
                outputPipeline,
                bankComposition,
                pipelinePalettes,
                glyphMaterialMetadata,
                sceneBankMetadata,
                sceneBankValidation,
                diagnostics);
    }

    public AssetWorkspaceAssetDetails withGlyphMaterialMetadata(AssetStudioGlyphMaterialMetadata glyphMaterialMetadata) {
        return new AssetWorkspaceAssetDetails(
                summary,
                actions,
                outputFormat,
                outputCodec,
                availableOutputCodecs,
                codecConfigurationFieldsByCodec,
                metadataFields,
                outputPipeline,
                bankComposition,
                pipelinePalettes,
                glyphMaterialMetadata,
                sceneBankMetadata,
                sceneBankValidation,
                diagnostics);
    }

    public AssetWorkspaceAssetDetails withSceneBankMetadata(AssetStudioSceneBankMetadata sceneBankMetadata) {
        return new AssetWorkspaceAssetDetails(
                summary,
                actions,
                outputFormat,
                outputCodec,
                availableOutputCodecs,
                codecConfigurationFieldsByCodec,
                metadataFields,
                outputPipeline,
                bankComposition,
                pipelinePalettes,
                glyphMaterialMetadata,
                sceneBankMetadata,
                sceneBankValidation,
                diagnostics);
    }
}
