package p.studio.workspaces.assets;

import p.packer.messages.AssetReference;
import p.studio.workspaces.assets.messages.AssetWorkspaceAssetSummary;
import p.studio.workspaces.assets.messages.AssetWorkspaceStatus;

import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

public record AssetWorkspaceState(
        AssetWorkspaceStatus status,
        List<AssetWorkspaceAssetSummary> assets,
        AssetReference selectedAssetReference,
        String errorMessage) {

    public AssetWorkspaceState {
        Objects.requireNonNull(status, "status");
        assets = List.copyOf(Objects.requireNonNull(assets, "assets"));
    }

    public static AssetWorkspaceState loading(AssetWorkspaceState previous) {
        if (previous == null) {
            return new AssetWorkspaceState(AssetWorkspaceStatus.LOADING, List.of(), null, null);
        }
        return new AssetWorkspaceState(AssetWorkspaceStatus.LOADING, previous.assets(), previous.selectedAssetReference(), null);
    }

    public static AssetWorkspaceState ready(List<AssetWorkspaceAssetSummary> assets, AssetReference preferredAssetReference) {
        final List<AssetWorkspaceAssetSummary> normalizedAssets = normalizeAssets(assets);
        final AssetReference resolvedSelection = reconcileSelection(normalizedAssets, preferredAssetReference);
        final AssetWorkspaceStatus status = normalizedAssets.isEmpty() ? AssetWorkspaceStatus.EMPTY : AssetWorkspaceStatus.READY;
        return new AssetWorkspaceState(status, normalizedAssets, resolvedSelection, null);
    }

    public static AssetWorkspaceState error(AssetWorkspaceState previous, String errorMessage) {
        return new AssetWorkspaceState(
                AssetWorkspaceStatus.ERROR,
                previous == null ? List.of() : previous.assets(),
                previous == null ? null : previous.selectedAssetReference(),
                Objects.requireNonNullElse(errorMessage, "Unknown asset workspace error"));
    }

    public Optional<AssetWorkspaceAssetSummary> selectedAsset() {
        if (selectedAssetReference == null) {
            return Optional.empty();
        }
        return assets.stream()
                .filter(asset -> asset.assetReference().equals(selectedAssetReference))
                .findFirst();
    }

    public AssetWorkspaceState withSelection(AssetReference nextAssetReference) {
        final AssetReference resolvedSelection = reconcileSelection(assets, nextAssetReference);
        return new AssetWorkspaceState(status, assets, resolvedSelection, errorMessage);
    }

    static AssetReference reconcileSelection(
            List<AssetWorkspaceAssetSummary> assets,
            AssetReference preferredAssetReference) {
        if (assets.isEmpty()) {
            return null;
        }
        if (preferredAssetReference != null) {
            for (AssetWorkspaceAssetSummary asset : assets) {
                if (asset.assetReference().equals(preferredAssetReference)) {
                    return preferredAssetReference;
                }
            }
        }
        return assets.getFirst().assetReference();
    }

    private static List<AssetWorkspaceAssetSummary> normalizeAssets(List<AssetWorkspaceAssetSummary> assets) {
        return List.copyOf(Objects.requireNonNull(assets, "assets").stream()
                .sorted(Comparator
                        .comparing((AssetWorkspaceAssetSummary asset) -> asset.assetRoot().toString(), String.CASE_INSENSITIVE_ORDER)
                        .thenComparing(AssetWorkspaceAssetSummary::assetName, String.CASE_INSENSITIVE_ORDER))
                .toList());
    }
}
