// Options.cpp: Implementierungsdatei
//

#include "stdafx.h"
#include "afxmt.h"
#include "ConsoleApp.h"
#include "Options.h"

#include "MarkupSTL.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

bool             COptions::m_bInitialized = false;
CString          COptions::m_sConfigFile  = "";
CCriticalSection COptions::m_csSync;
CMarkupSTL       COptions::m_markup;

COptions::OPTIONCACHE_STRUCT COptions::m_aoc[OPTIONS_NUM];

/////////////////////////////////////////////////////////////////////////////
// Dialogfeld COptions

typedef struct
{
	TCHAR szName[35];
	int   type;
} OPTION_STRUCT;

static OPTION_STRUCT g_aopt[OPTIONS_NUM] = {
	_T("Windows Position"),				0,	_T("Splitter Size"),				0,
	_T("Remote Tree Size"),				1,	_T("Local Tree Size"),				1,
	_T("Show Remote Tree"),				1,	_T("Show Local Tree"),				1,
	_T("Remote List Style"),			1,	_T("Local List Style"),				1,
	_T("Show Remote Status"),			1,	_T("Show Local Status"),			1,
	_T("Remote Column Widths"),			0,	_T("Local Column Widths"),			0,
	_T("Remote Column Sort"),			1,	_T("Local Column Sort"),			1,
	_T("Show Top Toolbar"),				1,	_T("Show Mid Toolbar"),				1,
	_T("User ID"),						0,	_T("Password"),						0,
	_T("Auto Connect"),					1,	_T("Save Password"),				1,
	_T("File Exists Action"),			1,
	_T("After Execution"),				1,
	_T("Search Sub Url"),				1,	_T("Url Tag Type"),					1,
	_T("Url Start Tag"),				0,	_T("Url End Tag"),					0,
	_T("Proxy Host"),					0,	_T("Proxy Port"),					0,
	_T("Use IE Proxy"),					1,	_T("Write Policy"),					1,
	_T("Admin Name 01"),				0,
	_T("Admin Name 02"),				0,
	_T("Admin Name 03"),				0,
	_T("Admin Phone 01"),				0,
	_T("Admin Phone 02"),				0,
	_T("Admin Phone 03"),				0,
	_T("Admin Mail 01"),				0,
	_T("Admin Mail 02"),				0,
	_T("Admin Mail 03"),				0,
	_T("Log Directory"),				1,
	_T("Log Upload File"),				1
};


void COptions::SetOption(int nOptionID,int nValue)
{
	ASSERT(g_aopt[(OPTION_TYPE)nOptionID].type == OT_NUMBER);

	CSingleLock lock(&m_csSync, TRUE);

	m_aoc[nOptionID].bCached = true;
	m_aoc[nOptionID].type    = OT_NUMBER;
	m_aoc[nOptionID].nValue  = nValue;

	m_markup.ResetPos();
	if (!m_markup.FindChildElem(_T("Settings")))
		m_markup.AddChildElem(_T("Settings"));

	CString sValue;
	sValue.Format(_T("%d"), nValue);

	m_markup.IntoElem();
	BOOL bRet = m_markup.FindChildElem();
	while (bRet) {
		CString sName = m_markup.GetChildAttrib( _T("name"));

		if (_tcscmp(sName, g_aopt[nOptionID].szName) == 0) {
			m_markup.SetChildAttrib(_T("name"), g_aopt[nOptionID].szName);
			m_markup.SetChildAttrib(_T("type"), _T("numeric"));
			m_markup.SetChildData(sValue);
			break;
		}

		bRet = m_markup.FindChildElem();
	}

	if (!bRet) {
		m_markup.InsertChildElem(_T("Item"), sValue);
		m_markup.SetChildAttrib(_T("name"),  g_aopt[nOptionID].szName);
		m_markup.SetChildAttrib(_T("type"),  _T("numeric"));
	}

	m_markup.Save(m_sConfigFile);
}

void COptions::SetOption(int nOptionID, CString sValue)
{
	ASSERT((OPTION_TYPE)g_aopt[nOptionID].type == OT_STRING);

	CSingleLock lock(&m_csSync, TRUE);

	m_aoc[nOptionID].bCached = true;
	m_aoc[nOptionID].type    = OT_STRING;
	m_aoc[nOptionID].sValue  = sValue;

	m_markup.ResetPos();
	if (!m_markup.FindChildElem(_T("Settings")))
		m_markup.AddChildElem(_T("Settings"));

	m_markup.IntoElem();

	CString sTag;
	sTag = m_markup.GetTagName();

	BOOL bRet = m_markup.FindChildElem();
	while (bRet) {
		CString sName = m_markup.GetChildAttrib(_T("name"));
		if (_tcscmp(sName, g_aopt[nOptionID].szName) == 0) {
			m_markup.SetChildAttrib(_T("name"), g_aopt[nOptionID].szName);
			m_markup.SetChildAttrib(_T("type"), _T("string"));
			m_markup.SetChildData(sValue);
			break;
		}

		bRet = m_markup.FindChildElem();
	}

	if (!bRet) {
		m_markup.InsertChildElem(_T("Item"), sValue);
		m_markup.SetChildAttrib(_T("name"),  g_aopt[nOptionID].szName);
		m_markup.SetChildAttrib(_T("type"),  _T("string"));
	}

	m_markup.Save(m_sConfigFile);
}

int COptions::GetOptionVal(int nOptionID)
{
	ASSERT((OPTION_TYPE)g_aopt[nOptionID].type == OT_NUMBER);

	CSingleLock lock(&m_csSync, TRUE);

	int nResult = m_aoc[nOptionID].nValue;
	if (!m_aoc[nOptionID].bCached) {
		switch (nOptionID) {
		case OPTION_SHOWTOPTOOLBAR:
		case OPTION_SHOWMIDTOOLBAR:
			nResult = 1;
			break;
		case OPTION_SHOWLOCALTREE:
		case OPTION_SHOWREMOTETREE:
			nResult = 1;
			break;
		case OPTION_SHOWLOCALSTATUS:
		case OPTION_SHOWREMOTESTATUS:
			nResult = 1;
			break;
		case OPTION_LOCALTREESIZE:
		case OPTION_REMOTETREESIZE:
			nResult = 300;
			break;
		case OPTION_LOCALLISTSTYLE:
		case OPTION_REMOTELISTSTYLE:
			nResult = 4;
			break;
		case OPTION_USEIEPROXY:
		case OPTION_SEARCHSUBURL:
			nResult = 1;
			break;
		}
	}

	return nResult;
}

CString COptions::GetOption(int nOptionID)
{
	ASSERT((OPTION_TYPE)g_aopt[nOptionID].type == OT_STRING);

	CSingleLock lock(&m_csSync, TRUE);

	CString sResult = m_aoc[nOptionID].sValue;
	if (!m_aoc[nOptionID].bCached) {
//		if (nOptionID == OPTION_URLDIVIDER)
//			sResult = _T("|");
	}

	return sResult;
}

bool COptions::Init(LPCTSTR pszConfigFile)
{
	CSingleLock lock(&m_csSync, TRUE);

	if (m_bInitialized)
		return true;

	m_sConfigFile = pszConfigFile;

	m_bInitialized = true;

	for (int i = 0; i < OPTIONS_NUM; i++)
		m_aoc[i].bCached = false;

	CFileStatus64 fs;
	if (!GetStatus64(m_sConfigFile, fs) || fs.m_size <= 45) {
		m_markup.AddElem(_T(APP_TITLE));
		m_markup.Save(m_sConfigFile);
	}
	else if (fs.m_attribute & FILE_ATTRIBUTE_DIRECTORY)
		return false;

	if (!m_markup.Load(m_sConfigFile))
		return false;

	if (!m_markup.FindElem(_T(APP_TITLE)))
		return false;

	if (!m_markup.FindChildElem(_T("Settings")))
		m_markup.AddChildElem(_T("Settings"));

	CString sTag;

	m_markup.IntoElem();
	sTag = m_markup.GetTagName();
	while (m_markup.FindChildElem()) {
		CString sValue = m_markup.GetChildData();
		CString sName  = m_markup.GetChildAttrib(_T("name"));
		CString sType  = m_markup.GetChildAttrib(_T("type"));

		for (int i = 0;i < OPTIONS_NUM; i++) {
			if (_tcscmp(sName, g_aopt[i].szName) == 0) {
				m_aoc[i].bCached = true;
				if (sType == "numeric") {
					m_aoc[i].type   = OT_NUMBER;
					m_aoc[i].nValue = _ttoi(sValue);
				}
				else {
					if (sType != "string")
						::AfxTrace( _T("Unknown option type '%s' for item '%s', assuming string\n"), sType, sName);
					m_aoc[i].type   = OT_STRING;
					m_aoc[i].sValue = sValue;
				}
				break;
			}
		}
	}

	return true;
}
