#include "scripts/common.txt"
#include "scripts/bp_common.txt"
#include "scripts/Math.txt"
// funcdef void MenuSelectCallBack(void);

// enum MenuStates {
    // MENUSTATE_OPEN = 0,
    // MENUSTATE_CLOSED,
    // MENUSTATE_OPENING,
    // MENUSTATE_CLOSING
// }

//Text Menus
class MenuShop {
	int state = MENUSTATE_CLOSED;
	int index = 0;
	int cost = 0;
	kStr textInfo;
	kStr textCurrentMoney;
	kStr textTopOrignal;
	kStr textTop;
	kStr textMiddle;
	kStr textBottom;
	kStr textDivider;
	int textWait = 0;
	int infoTime = 0;
	int inputWait = 0;
	int closeTime = 0;
	int openTime = 0;
	MenuSelectCallBack @onSelectItem;
	//------------------------------------------------------------------------------------------------------------------------
	MenuShop() {
	}
	//------------------------------------------------------------------------------------------------------------------------
    MenuShop(const kStr &in topText, const kStr &in middleText, const kStr &in bottomText, const int newCost, MenuSelectCallBack @selectItemFunc) {
		textTopOrignal = topText;
		textMiddle = middleText;
		textBottom = bottomText;
		SetCost(newCost);
		//UpdateTexts();
		@onSelectItem = @selectItemFunc;
    }
	//------------------------------------------------------------------------------------------------------------------------
	void SetTopText(const kStr &in topText, int newCost) {
		textTopOrignal = topText;
		SetCost(newCost);
	}
	//------------------------------------------------------------------------------------------------------------------------
	void SetCost(const int newCost) {
		cost = newCost;
		textTop = textTopOrignal;
		textTop += " - " + cost + " Spirits~";
		UpdateTexts();
	}
	//------------------------------------------------------------------------------------------------------------------------
	void UpdateTexts() {
		textCurrentMoney = "" + GetMoney() + " Spirits Remaining~";
		textDivider = "";
		int textTopLength = GetTextLength(textTop);
		int textCurrentMoneyLength = GetTextLength(textTop);
		int dividerLength = textTopLength > textCurrentMoneyLength ? textTopLength : textCurrentMoneyLength;
		for (int i = 0; i < dividerLength; i++) {
			textDivider += "-";
		}
	}
	//------------------------------------------------------------------------------------------------------------------------
	int GetTextLength(kStr text) {
		int maxSize = 1000; //would most likely crash because of index out of range before this happens
		int size = 0;
		int i = 0;
		while (true) {
			//char equals ~
			if (text[i] == 126 or i >= maxSize) {
				break;
			}
			i++;
		}
		return i;
	}
	//------------------------------------------------------------------------------------------------------------------------
	void Open() {
		state = MENUSTATE_OPENING;
		index = 0;
		textWait = 0;
		infoTime = 0;
		inputWait = 0;
		closeTime = 0;
		openTime = 30;
		UpdateTexts();
	}
	//------------------------------------------------------------------------------------------------------------------------
	void Close() {
		if (IsOpen()) {
			state = MENUSTATE_CLOSING;
			closeTime = 30;
		}
	}
	//------------------------------------------------------------------------------------------------------------------------
	bool IsOpen() {
		return state == MENUSTATE_OPEN;
	}
	//------------------------------------------------------------------------------------------------------------------------
	bool IsClosed() {
		return state == MENUSTATE_CLOSED;
	}
	//------------------------------------------------------------------------------------------------------------------------
	bool IsOpening() {
		return state == MENUSTATE_OPENING;
	}
	//------------------------------------------------------------------------------------------------------------------------
	bool IsClosing() {
		return state == MENUSTATE_CLOSING;
	}
	//------------------------------------------------------------------------------------------------------------------------
	void DisplayInfoText(const kStr &in text, const int time) {
		textInfo = text;
		infoTime = time;
	}
	//------------------------------------------------------------------------------------------------------------------------
	void OnBuy() {
		if (HasMoney(cost)) {
			LoseMoney(cost);
			Game.PlaySound("sounds/shaders/generic_178.ksnd"); //bought item
			onSelectItem();
			Close();
		} else {
			Game.PlaySound("sounds/shaders/generic_167.ksnd"); //not enough money
			DisplayInfoText("Not enough Spirits", 60);
		}
	}
	//------------------------------------------------------------------------------------------------------------------------
	void OnCancel() {
		Game.PlaySound("sounds/shaders/generic_195.ksnd");
		Close();
	}
	//------------------------------------------------------------------------------------------------------------------------
	void OnClosed() {
		SetPlayerFlagNoMovement(false);
	}
	//------------------------------------------------------------------------------------------------------------------------
	bool IsInfoDisplaying() {
		return infoTime > 0;
	}
	//------------------------------------------------------------------------------------------------------------------------
	void Update() {
		if (IsOpening()) {
			openTime--;
			if (openTime <= 0) {
				state = MENUSTATE_OPEN;
			}
		} else if (IsClosing()) {
			closeTime--;
			if (closeTime <= 0) {
				state = MENUSTATE_CLOSED;
				OnClosed();
			}
		}
		
		if (IsOpen() and !IsInfoDisplaying()) {
			uint16 buttons = Player.Buttons();
			if (inputWait > 0) {
				inputWait = Math::Max(inputWait - 1, 0);
			} else {
				if ((buttons & BC_FORWARD) != 0) {
					Game.PlaySound("sounds/shaders/generic_89_jump_swish_1.ksnd");
					inputWait = 10;
					index--;
					if (index < 0) {
						index = 1;
					}
				} else if ((buttons & BC_BACKWARD) != 0) {
					Game.PlaySound("sounds/shaders/generic_89_jump_swish_1.ksnd");
					inputWait = 10;
					index++;
					if (index > 1) {
						index = 0;
					}
				} else if ((buttons & BC_JUMP) != 0 or (buttons & BC_ATTACK) != 0) {
					inputWait = 10;
					if (index == 0) {
						OnBuy();
					} else {
						OnCancel();
					}
				}
			}
		}
		
		if (textWait > 0) {
			textWait--;
		} else {
			if (IsOpen() or IsOpening()) {
				if (IsInfoDisplaying()) {
					Game.PrintLine(textInfo, 0, 10);
					infoTime--;
					if (!IsInfoDisplaying()) {
						textWait = 10;
					}
				} else {
					Game.PrintLine((index == 1 ? "- " : "") + textBottom + (index == 1 ? " -" : ""), 0, 10); //bottom
					Game.PrintLine((index == 0 ? "- " : "") + textMiddle + (index == 0 ? " -" : ""), 1, 10);
					Game.PrintLine(textDivider, 2, 10);
					Game.PrintLine(textTop, 3, 10);
					Game.PrintLine(textDivider, 4, 10);
					Game.PrintLine(textCurrentMoney, 5, 10); //top
				}
			}
		}
	}
	//------------------------------------------------------------------------------------------------------------------------
};
