#pragma once

#include "structs.hpp"
#include "launcher/launcher.hpp"

#define SELECT_VALUE(sp, mp) (game::environment::is_sp() ? (sp) : (mp))

#define SERVER_CD_KEY "H1MOD-CD-Key"

namespace game
{
	extern uint64_t base_address;
	void load_base_address();

	namespace environment
	{
		launcher::mode get_mode();
		launcher::mode get_real_mode();

		bool is_sp();
		bool is_mp();
		bool is_dedi();

		void set_mode(launcher::mode mode);

		std::string get_string();
	}

	template <typename T>
	class symbol
	{
	public:
		symbol(const size_t sp_address, const size_t mp_address)
			: sp_object_(reinterpret_cast<T*>(sp_address))
			, mp_object_(reinterpret_cast<T*>(mp_address))
		{
		}

		T* get() const
		{
			if (environment::is_sp())
			{
				return reinterpret_cast<T*>((uint64_t)sp_object_ + base_address);
			}

			return reinterpret_cast<T*>((uint64_t)mp_object_ + base_address);
		}

		operator T* () const
		{
			return this->get();
		}

		T* operator->() const
		{
			return this->get();
		}

	private:
		T* sp_object_;
		T* mp_object_;
	};

	int Cmd_Argc();
	const char* Cmd_Argv(int index);

	int SV_Cmd_Argc();
	const char* SV_Cmd_Argv(int index);

	bool VirtualLobby_Loaded();

	void SV_GameSendServerCommand(int clientNum, svscmd_type type, const char* text);

	void Cbuf_AddText(int local_client_num, int controller_index, const char* cmd);

	void Cmd_TokenizeString(const char* text);
	void Cmd_EndTokenizeString();
}

uintptr_t operator"" _b(const uintptr_t ptr);

#include "symbols.hpp"
