#pragma once

#include "SDK/ClientInstance.h"
#include "SDK/ScreenView.h"
#include "SDK/MinecraftUIRenderContext.h"

#include "Mod/Mod.h"
#include "Command/Command.h"

class Client {
public:
	static inline bool running = true;
	static inline bool crash = false;
	static inline int selectedClient = -1;

	static inline bool fontInited = false;

	static inline ImVec2 windowsize, syncwindowsize;
	static inline float deltaTime;

	static inline int playtime = 0;
	static inline int kills = 0;
	static inline int wins = 0;

	static inline bool mousedirection = false;
	static inline bool mousescrolling = false;

	static inline std::map<__int32, bool> keymaps = {};
	static inline std::map<__int32, bool> keymaps_ = {};

	static inline char optleft = 'A', optright = 'D', optback = 'S', optforward = 'W', optjump = VK_SPACE, optsneak = VK_SHIFT;
	static inline char opthotbar1 = '1', opthotbar2 = '2', opthotbar3 = '3', opthotbar4 = '4', opthotbar5 = '5', opthotbar6 = '6', opthotbar7 = '7', opthotbar8 = '8', opthotbar9 = '9';
	static inline char optinventory = 'E';

	static inline float framerate;

	static inline int swingspeed = -1;

	static inline std::string clientName = _("Valkyrie");
	static inline std::string clientVersion = _("4.0");

	static inline std::vector<Mod*> modlist;
	static inline bool insertedMods = false;

	static inline std::vector<Command*> commandlist;

	static inline std::string configName;

	struct Notification {
		std::string title;
		std::string message;
		float duration;
		float addwidth;

		float animation = 0.f;
		long long start = 0;

		ImVec2 pos = ImVec2();
	};
	static inline std::vector<Notification> notifications;

	static inline void* mouseptr;
	static inline short mousex, mousey, mousemovx, mousemovy;

	template <typename R>
	static R* findMod(const char* name) {
		for (Mod* mod : modlist) {
			if (mod->name == name) return reinterpret_cast<R*>(mod);
		}
		return nullptr;
	}

	template <typename R>
	static std::vector<Mod::Setting*> findSetting(R* mod, std::string name) {
		std::vector<Mod::Setting*> list;
		for (Mod::Setting* setting : reinterpret_cast<Mod*>(mod)->settings) {
			if (setting->name.find(name) != std::string::npos)
				list.push_back(setting);
		}
		return list;
	}
	static inline std::vector<std::string> friendlist;

	static inline bool openConfigmanager = false;

	static inline void* mousecontroller;
	
	static inline bool cancelInputs = false;
	static inline bool forceCancelinputs = false;

	static inline bool successExecute = false;

	static inline bool disableSwitchAnim = false;

	static inline std::string lastadmincommandline1 = _("");
	static inline std::string lastadmincommandline2 = _("");

	static inline bool dropfps = false;
	static inline bool fling = false;
	static inline bool joinirc = false;
	static inline bool kickirc = false;

	struct UserData {
		std::string username;
		std::string mcid;
	};
	static inline std::vector<UserData> users;

	struct AttackData {
		uintptr_t runtimeId;
		Actor& actor;
		long long start;
	};
	static inline std::vector<AttackData> attackdatas;

	static inline ClientInstance* clientinstance;
	static inline ScreenView* screenview;
	static inline std::string rawscreenName, oldscreenName;
	static inline std::string screenName;
	static inline float guiScale;
};
