#pragma once

struct INI_KEY_STRUCT
{
	DWORD Hash;
	CString Key;
	CString Value;
	CString Comment;
	INI_KEY_STRUCT *next;
};

struct INI_SECTION_STRUCT
{
	DWORD Hash;
	CString Name;
	INI_KEY_STRUCT *Keys;
	INI_SECTION_STRUCT *next;
};

enum IniStatus {INI_NOTREADED = 0, INI_READED, INI_FLUSHED};
enum IniError {INI_OK = 0, INI_READERROR, INI_WRITEERROR, INI_PARSEERROR};

#define INI_BUFFER_LENGTH 1024

class CIni
{
	private:

		CString m_strFileName; //Имя ини файла
		IniStatus m_iniStatus;
		IniError m_iniError;
		int m_LineNum;
		int m_Encoding; //0 - utf8, 1 - ansi -- сейчас не используется. Только АНСИ

		INI_SECTION_STRUCT *SetOfSections;

		BOOL ReadIni();
		DWORD GetHash(const CString &str);
		BOOL Add(CString strSection, CString strKey, CString strVal, CString strComm, BOOL bChangeComment = FALSE);

		LPSTR ConvertUnicodetoStr(UINT type, const CString &ustr); //type = CP_ACP - ansi; CP_UTF8 - utf8
		CString ConvertStrtoUnicode(UINT type, LPCSTR astr); //type = CP_ACP - ansi; CP_UTF8 - utf8

	public:
		CIni();
		virtual ~CIni();
		BOOL FlushIni();
		ULONGLONG FlushIniToMemory(BYTE *pBuff, UINT nSize);
		BOOL ReadIniFromMemory(BYTE *pBuff, UINT nSize);
		void Clear();

		CString GetValueString(int nSection, int nKey, const CString &strDefault);
		int     GetValueInt(int nSection, int nKey, const int nDefault);
		int     GetValueOct(int nSection, int nKey, const int nDefault);
		double  GetValueFloat(int nSection, int nKey, const double fDefault);
		BOOL    GetValueBool(int nSection, int nKey, const BOOL bDefault);

		BOOL    SetValueString(int nSection, int nKey, const CString &strVal);
		BOOL    SetValueInt(int nSection, int nKey, const int iVal);
		BOOL    SetValueOct(int nSection, int nKey, const int oVal);
		BOOL    SetValueFloat(int nSection, int nKey, const double fVal);
		BOOL    SetValueBool(int nSection, int nKey, const BOOL bVal);

		inline void SetIniFileName(const CString &strFileName)
		{
			m_strFileName = strFileName;
		}
		inline const CString &GetIniFileName()
		{
			return m_strFileName;
		}
		inline IniStatus GetIniStatus()
		{
			return m_iniStatus;
		}
		inline IniError GetIniError()
		{
			return m_iniError;
		}
		inline void SetEncoding(int e)
		{
			m_Encoding = e;
		}
		inline int GetEncoding()
		{
			return m_Encoding;
		}
};

