#pragma once
// тут будут храниться всякие глобальные параметры и флаги

#include "Reader.h"

struct Registers_t
{
	int nNum{ 0 };
	std::vector<CBKToken>names;
};

enum class OPERAND_TYPE
{
	SRC,
	DST
};

enum class LINKING_MODE
{
	CL,
	CO,
	FINAL
};

// флаги типа арифметической операции
constexpr uint32_t ARITHM_NOBRACKETS    = (1 << 0); // без скобок, только вычисления
constexpr uint32_t ARITHM_NOLOCLABEL    = (1 << 1); // без локальных меток
constexpr uint32_t ARITHM_NOUNDLABEL    = (1 << 2); // без неопределённых меток
// как я заметил, флаг ARITHM_NOUNDLABEL не используется. В текущей логике разбора
// в нём нет необходимости, но он везде устанавливается где есть это требование
constexpr uint32_t ARITHM_INBRANCH      = (1 << 3); // в командах ветвления (влияет на обработку точки)

// флаги-опции
constexpr uint32_t BKT_GLBL_VERBOSITY   = (1 << 0); // флаг вывода больше информации на экран
constexpr uint32_t BKT_GLBL_INSCRIPT    = (1 << 1); // флаг, что обрабатываем скрипт.
constexpr uint32_t BKT_GLBL_INSTRING    = (1 << 2); // флаг, что находимся внутри строки "" для ascii, asciz и rad50
constexpr uint32_t BKT_GLBL_ENDREACHED  = (1 << 3); // флаг, что встретилась псевдокоманда .end
constexpr uint32_t BKT_GLBL_STOPONERROR = (1 << 4); // флаг остановки компиляции при первой встреченной ошибке
constexpr uint32_t BKT_GLBL_STEPINCLUDE = (1 << 5); // флаг, который говорит, что мы вошли в новую инклуду и надо начать цикл сначала
constexpr uint32_t BKT_GLBL_ININCLUDE   = (1 << 6); // флаг, который говорит, что инклуда обрабатывается.
constexpr uint32_t BKT_GLBL_SETENABL    = (1 << 7); // флаг команды ENABL, трактующей выполнять адресацию 67 как 37

class GlobalParams
{
		fs::path                m_pathAppPath;   // домашний путь
		fs::path                m_pathInclude;  // текущий путь поиска иклуд и инсертов, каждый раз задаётся для
		// нового открываемого асм файла
		CReader::FILE_CHARSET   m_Charset{CReader::FILE_CHARSET::UNDEFINE}; // текущая кодировка исходника
		std::vector <std::wstring> m_vAddIncludes; // вектор, куда помещаются все добавленные инклуды
		std::vector <CReader *> m_vReader;      // вектор, куда помещаются реадеры при обработке инклуд

		OPERAND_TYPE            m_nOperandType{ OPERAND_TYPE::SRC }; // тип обрабатываемого операнда
		LINKING_MODE            m_nLinkMode{ LINKING_MODE::CL }; // режим компоновки меток: CL, CO, FINAL = окончательная компоновка после .end
		uint32_t                m_nArithmeticType{ 0 }; // тип арифметического выражения, где оно встречается: -1 = константа, 1 - word или ассемблерная команда, 0 - все остальное

		uint32_t                m_nFlags{ 0 };      // флаги-опции
		int                     m_nLinkAddr{ 0 };   // адрес, с которого начинается линковка очередного объектного файла

		int                     m_nStartAddress{ 0 }; // смещение адреса начала трансляции проги относительно 01000 == по-умолчанию
		int                     m_nPC{ 0 };         // текущий PC при компиляции, измеряется в байтах.
		int                     m_nProgramLength{ 0 }; // длина компилируемой программы
		int                     m_nErrors{ 0 };     // флаг возникновения ошибки, и одновременно счётчик.
		int                     m_nWarnings{ 0 };   // счётчик предупреждений.

		int                     m_nLinkObjLen{0};   // размер прилинковываемого объектного файла
	public:
		GlobalParams() noexcept
		{
			InitGlobalParameters();
		}

		void                InitGlobalParameters();
		void                ReInitGlobalParameters();

		void                SetBasePath(const fs::path &path)
		{
			m_pathAppPath = path;
		}
		const fs::path      GetBasePath() const
		{
			return m_pathAppPath;
		}

		void                SetIncludePath(const fs::path &path)
		{
			m_pathInclude = path;
		}
		const fs::path      GetIncludePath() const
		{
			return m_pathInclude;
		}

		void                SetCharset(const CReader::FILE_CHARSET chs) noexcept
		{
			m_Charset = chs;
		}
		CReader::FILE_CHARSET GetCharset() const noexcept
		{
			return m_Charset;
		}

		void                SetVerbosity(const bool b) noexcept;
		bool                isVerbosity() const noexcept;

		void                SetInScript(const bool b) noexcept;
		bool                isInScript() const noexcept;

		void                SetInString(const bool b) noexcept;
		bool                isInString() const noexcept;

		void                SetENDReached(const bool b) noexcept;
		bool                isENDReached() const noexcept;

		void                SetStopOnError(const bool b) noexcept;
		bool                isStopOnError() const noexcept;

		void                SetLinkerAddr(const int n) noexcept;
		int                 GetLinkerAddr() const noexcept;

		void                SetStepInclude(const bool b) noexcept;
		bool                isStepInclude() const noexcept;

		void                SetInInclude(const bool b) noexcept;
		bool                isInInclude() const noexcept;

		void                SetEnabl(const bool b) noexcept;
		bool                isEnabl() const noexcept;

		void                SetOperandType(const OPERAND_TYPE ot) noexcept
		{
			m_nOperandType = ot;
		}
		OPERAND_TYPE        GetOperandType() const noexcept
		{
			return m_nOperandType;
		}

		void                SetLinkMode(const LINKING_MODE lm) noexcept
		{
			m_nLinkMode = lm;
		}
		LINKING_MODE        GetLinkMode() const noexcept
		{
			return m_nLinkMode;
		}

		void                SetArithmeticType(const uint32_t at) noexcept
		{
			m_nArithmeticType = at;
		}
		uint32_t            GetArithmeticType() const noexcept
		{
			return m_nArithmeticType;
		}

		void                SetPC(const int pc) noexcept
		{
			m_nPC = pc;
		}
		int                 GetPC() const noexcept
		{
			return m_nPC;
		}

		void                SetProgramLength(const int l) noexcept
		{
			m_nProgramLength = l;
		}
		int                 GetProgramLength() const noexcept
		{
			return m_nProgramLength;
		}

		void                SetLinkObjLength(const int l) noexcept
		{
			m_nLinkObjLen = l;
		}

		void                GrowLinkObjLength() noexcept;

		void                SetError(const int n) noexcept
		{
			m_nErrors = n;
		}
		int                 GetError() const noexcept
		{
			return m_nErrors;
		}

		void                SetWarning(const int n) noexcept
		{
			m_nWarnings = n;
		}
		int                 GetWarning() const noexcept
		{
			return m_nWarnings;
		}

		void                SetStartAddress(const int addr) noexcept
		{
			m_nStartAddress = addr;
		}
		int                 GetStartAddress() const noexcept
		{
			return m_nStartAddress & 0xffff;
		}

		int                 GetRealAddress(const int addr) const noexcept;
		int                 CorrectOffset(const int addr) const noexcept;
		bool                FindReader(const fs::path &strFileName);
		void                PushReader(CReader *r);
		CReader            *PopReader() noexcept;
		int                 StrToDec(const std::string &str);
		int                 StrToOct(const std::string &str);
		int                 StrToDec(const std::wstring &str);
		int                 StrToOct(const std::wstring &str);
};

extern GlobalParams g_Globals;
extern CReader *g_pReader;
extern std::vector <Registers_t> g_RegNames;

