package p.studio.workspaces.assets.details.contract;

import p.packer.messages.AssetReference;
import p.packer.messages.assets.OutputCodecCatalog;
import p.packer.messages.assets.OutputFormatCatalog;
import p.studio.workspaces.assets.messages.AssetWorkspaceAssetDetails;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;

public record AssetContractDraft(
        AssetReference assetReference,
        boolean preload,
        OutputFormatCatalog bank,
        OutputCodecCatalog selectedCodec,
        Map<String, String> codecFieldValues,
        Map<String, String> metadataFieldValues) {

    public AssetContractDraft {
        Objects.requireNonNull(assetReference, "assetReference");
        bank = Objects.requireNonNullElse(bank, OutputFormatCatalog.UNKNOWN);
        selectedCodec = Objects.requireNonNullElse(selectedCodec, OutputCodecCatalog.UNKNOWN);
        codecFieldValues = Map.copyOf(Objects.requireNonNull(codecFieldValues, "codecFieldValues"));
        metadataFieldValues = Map.copyOf(Objects.requireNonNull(metadataFieldValues, "metadataFieldValues"));
    }

    public static AssetContractDraft fromDetails(AssetWorkspaceAssetDetails details) {
        final Map<String, String> codecFieldValues = new LinkedHashMap<>();
        details.codecConfigurationFieldsByCodec().forEach((codec, fields) ->
                fields.forEach(field -> codecFieldValues.put(keyOf(codec, field.key()), field.value())));
        final Map<String, String> metadataFieldValues = new LinkedHashMap<>();
        details.metadataFields().forEach(field -> metadataFieldValues.put(field.key(), field.value()));
        return new AssetContractDraft(
                details.summary().assetReference(),
                details.summary().preload(),
                details.outputFormat(),
                details.outputCodec(),
                codecFieldValues,
                metadataFieldValues);
    }

    public AssetContractDraft withPreload(boolean preload) {
        return new AssetContractDraft(assetReference, preload, bank, selectedCodec, codecFieldValues, metadataFieldValues);
    }

    public AssetContractDraft withSelectedCodec(OutputCodecCatalog selectedCodec) {
        return new AssetContractDraft(assetReference, preload, bank, selectedCodec, codecFieldValues, metadataFieldValues);
    }

    public AssetContractDraft withCodecFieldValue(OutputCodecCatalog codec, String fieldKey, String value) {
        final Map<String, String> nextValues = new LinkedHashMap<>(codecFieldValues);
        nextValues.put(keyOf(codec, fieldKey), Objects.requireNonNullElse(value, ""));
        return new AssetContractDraft(assetReference, preload, bank, selectedCodec, nextValues, metadataFieldValues);
    }

    public AssetContractDraft withMetadataFieldValue(String fieldKey, String value) {
        final Map<String, String> nextValues = new LinkedHashMap<>(metadataFieldValues);
        nextValues.put(fieldKey, Objects.requireNonNullElse(value, ""));
        return new AssetContractDraft(assetReference, preload, bank, selectedCodec, codecFieldValues, nextValues);
    }

    public String codecFieldValue(OutputCodecCatalog codec, String fieldKey, String fallback) {
        return codecFieldValues.getOrDefault(keyOf(codec, fieldKey), Objects.requireNonNullElse(fallback, ""));
    }

    public String metadataFieldValue(String fieldKey, String fallback) {
        return metadataFieldValues.getOrDefault(fieldKey, Objects.requireNonNullElse(fallback, ""));
    }

    private static String keyOf(OutputCodecCatalog codec, String fieldKey) {
        return codec.name() + ":" + fieldKey;
    }
}
