#pragma once

#include "LayerStackStore.h"
#include "RuntimeStoreReadModels.h"
#include "ShaderPackageCatalog.h"

#include <cstddef>
#include <string>
#include <vector>

class CommittedLiveState
{
public:
	using LayerPersistentState = LayerStackStore::LayerPersistentState;
	using StoredParameterSnapshot = LayerStackStore::StoredParameterSnapshot;

	bool LoadPersistentStateValue(const JsonValue& root);
	JsonValue BuildPersistentStateValue(const ShaderPackageCatalog& shaderCatalog) const;
	void NormalizeLayerIds();
	void EnsureDefaultsForAllLayers(const ShaderPackageCatalog& shaderCatalog);
	void EnsureDefaultLayer(const ShaderPackageCatalog& shaderCatalog);
	void RemoveLayersWithMissingPackages(const ShaderPackageCatalog& shaderCatalog);

	bool CreateLayer(const ShaderPackageCatalog& shaderCatalog, const std::string& shaderId, std::string& error);
	bool DeleteLayer(const std::string& layerId, std::string& error);
	bool MoveLayer(const std::string& layerId, int direction, std::string& error);
	bool MoveLayerToIndex(const std::string& layerId, std::size_t targetIndex, std::string& error);
	bool SetLayerBypassState(const std::string& layerId, bool bypassed, std::string& error);
	bool SetLayerShaderSelection(const ShaderPackageCatalog& shaderCatalog, const std::string& layerId, const std::string& shaderId, std::string& error);
	bool SetParameterValue(const std::string& layerId, const std::string& parameterId, const ShaderParameterValue& value, std::string& error);
	bool ResetLayerParameterValues(const ShaderPackageCatalog& shaderCatalog, const std::string& layerId, std::string& error);

	bool HasLayer(const std::string& layerId) const;
	bool TryGetParameterById(const ShaderPackageCatalog& shaderCatalog, const std::string& layerId, const std::string& parameterId, StoredParameterSnapshot& snapshot, std::string& error) const;
	bool TryGetParameterByControlKey(const ShaderPackageCatalog& shaderCatalog, const std::string& layerKey, const std::string& parameterKey, StoredParameterSnapshot& snapshot, std::string& error) const;
	bool ResolveLayerMove(const std::string& layerId, int direction, bool& shouldMove, std::string& error) const;
	bool ResolveLayerMoveToIndex(const std::string& layerId, std::size_t targetIndex, bool& shouldMove, std::string& error) const;

	JsonValue BuildStackPresetValue(const ShaderPackageCatalog& shaderCatalog, const std::string& presetName) const;
	bool LoadStackPresetValue(const ShaderPackageCatalog& shaderCatalog, const JsonValue& root, std::string& error);

	CommittedLiveStateReadModel BuildReadModel(const ShaderPackageCatalog& shaderCatalog) const;
	std::vector<LayerPersistentState> CopyLayerStates() const;
	const std::vector<LayerPersistentState>& Layers() const;
	std::vector<LayerPersistentState>& Layers();
	const LayerPersistentState* FindLayerById(const std::string& layerId) const;
	const LayerStackStore& LayerStack() const;
	LayerStackStore& LayerStack();

private:
	LayerStackStore mLayerStack;
};
