#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
};

enum class EasingType {
	Linear,
	EaseInSine,
	EaseOutSine,
	EaseInOutSine,
	EaseInQuad,
	EaseOutQuad,
	EaseInOutQuad,
	EaseInCubic,
	EaseOutCubic,
	EaseInOutCubic
};

enum class CutsceneAnchor {
	Center,
	TopLeft,
	TopRight,
	BottomRight,
	BottomLeft,
	Custom
};

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 backgroundWidth = 0;   // 0 = inherit from cutscene
	int backgroundHeight = 0;  // 0 = inherit from cutscene
	int durationMs = 0;
	bool waitForConfirm = false;
};

struct CutsceneCameraPose {
	CutsceneAnchor anchor = CutsceneAnchor::Center;

	// Используется только для Custom.
	// Нормализованные координаты 0..1, где:
	// centerX: 0 = левый край, 1 = правый край
	// centerY: 0 = верхний край, 1 = нижний край
	float centerX = 0.5f;
	float centerY = 0.5f;

	float zoom = 1.0f;
	float rotationDeg = 0.0f;
};

struct CutsceneCameraSegment {
	int durationMs = 0;
	CutsceneCameraPose from;
	CutsceneCameraPose to;
	EasingType easing = EasingType::EaseInOutSine;
};

struct CutsceneImageCue {
	std::string path;
	int startMs = 0;
	int endMs = 0;
	int fadeInMs = 0;
	int fadeOutMs = 0;
};

struct StaticCutsceneDefinition {
	std::string id;
	std::string background;
	int backgroundWidth = 1280;
	int backgroundHeight = 720;
	std::string music;
	bool skippable = true;
	int durationMs = 0;
	int fadeOutMs = 0;
	int fadeInMs = 0;
	int endFadeOutMs = 0;
	int endFadeInMs = 0;
	std::vector<CutsceneCameraSegment> cameraTrack;
	std::vector<CutsceneImageCue> images;
	std::vector<CutsceneLine> lines;
};

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

struct PresentedCutsceneImage {
	std::string path;
	float alpha = 1.0f;
};

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

struct CutsceneCameraBlendState {
	bool active = false;
	CutsceneCameraPose from;
	CutsceneCameraPose to;
	float t = 1.0f;
};

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 = -1;
	bool revealCompleted = true;
	bool showCutsceneSubtitle = false;
	bool cutsceneSkippable = false;

	CutsceneCameraBlendState cutsceneCamera;
	std::vector<PresentedCutsceneImage> cutsceneImages;
	float cutsceneGlobalFadeAlpha = 1.0f;
	float cutsceneBlackAlpha = 0.0f;
	int backgroundWidth = 1280;
	int backgroundHeight = 720;
};

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

} // namespace ZL::Dialogue
