#pragma once

#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

namespace ZL::Dialogue {

enum class NodeType {
	Line,
	Choice,
	Condition,
	SetFlag,
	Jump,
	End,
	CutsceneStart
};

enum class ChoiceKind {
	Main,
	Optional,
	Exit
};

enum class ComparisonOp {
	Exists,
	Equals,
	NotEquals,
	GreaterOrEqual,
	LessOrEqual
};

struct Condition {
	std::string flag;
	ComparisonOp op = ComparisonOp::Exists;
	int value = 1;
};

struct Effect {
	std::string flag;
	int value = 1;
	bool relative = false;
};

struct Choice {
	std::string id;
	std::string text;
	std::string next;
	ChoiceKind kind = ChoiceKind::Main;
	std::vector<Condition> conditions;
	std::vector<Effect> effects;
	bool consumeOnce = false;
};

struct Node {
	std::string id;
	NodeType type = NodeType::Line;

	std::string speaker;
	std::string text;
	std::string portrait;
	std::string next;

	// For Condition nodes
	std::string trueNext;
	std::string falseNext;
	std::vector<Condition> conditions;

	// For Choice / SetFlag
	std::vector<Choice> choices;
	std::vector<Effect> effects;

	// For CutsceneStart
	std::string cutsceneId;
};

struct DialogueDefinition {
	std::string id;
	std::string displayName;
	std::string startNode;
	std::unordered_map<std::string, Node> nodes;
};

struct CutsceneLine {
	std::string speaker;
	std::string text;
	std::string portrait;
	std::string sfx;
	std::string background;
	int durationMs = 0;
	bool waitForConfirm = false;
};

struct StaticCutsceneDefinition {
	std::string id;
	std::string background;
	std::string music;
	bool skippable = true;
	std::vector<CutsceneLine> lines;
};

struct PresentedChoice {
	std::string id;
	std::string text;
	ChoiceKind kind = ChoiceKind::Main;
};

enum class PresentationMode {
	Hidden,
	Dialogue,
	Choice,
	Cutscene
};

struct PresentationModel {
	PresentationMode mode = PresentationMode::Hidden;
	std::string dialogueId;
	std::string speaker;
	std::string fullText;
	std::string visibleText;
	std::string portraitPath;
	std::string backgroundPath;
	std::vector<PresentedChoice> choices;
	int selectedChoice = 0;
	bool revealCompleted = true;
};

struct SaveState {
	std::string dialogueId;
	std::string currentNodeId;
	std::string pendingNodeAfterCutscene;
	std::unordered_set<std::string, int> flags;
	std::unordered_set<std::string> consumedChoices;
	int selectedChoice = 0;
	int currentCutsceneLine = -1;
	int cutsceneTimerMs = 0;
	bool active = false;
};

} // namespace ZL::Dialogue