#include "stdafx.h"

#include "nlite_include.h"

namespace nlite{

	//
	//マクロ定義
	//
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define NLITE_GET_TYPENAME(n)			(_tcsstr(CComBSTR(typeid(n).name()),TEXT("::")) + 2)
#define NLITE_XMLELLMENT_WRITE(s,p)		s->WriteStartElement(NULL, NLITE_GET_TYPENAME(p), NULL)

#define NLITE_ELLEMENT_WRITE_STR(s,n)	s->WriteElementString(NULL, _tcsstr(TEXT(#n),TEXT("."))  != NULL ? _tcsstr(TEXT(#n),TEXT(".")) + 1 : TEXT(#n), NULL, n)


#define NLITE_ELLEMENT_WRITE_INT(s,n)	\
	{\
	TCHAR buffer[sizeof(n) * 8];\
	_stprintf(buffer,TEXT("%d"),static_cast<INT>(n));\
	s->WriteElementString(NULL, _tcsstr(TEXT(#n),TEXT(".")) + 1, NULL,buffer );\
}

#define NLITE_XML_WRITE_FOR_INT(s,n)\
	{\
	TCHAR nbuffer[LENGTH_256];\
	TCHAR buffer[sizeof(n[0]) * 8];\
	for(UINT_PTR index = 0;index < ARRAY_LENGTH(n);index++){\
	_stprintf(nbuffer,TEXT("%s%d"),_tcsstr(TEXT(#n),TEXT(".")) + 1,index);\
	_stprintf(buffer,TEXT("%d"),n[index]);\
	s->WriteElementString(NULL, nbuffer, NULL,buffer );\
	}\
}



	//
	//定数宣言
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	static const LPCTSTR headerFormat = TEXT("headerholSize%u");
	static const LPCTSTR headerOrderFormat = TEXT("headerOrderArray%u");
	static const LPCTSTR bt_none = TEXT("none");
	static const LPCTSTR bt_ie = TEXT("ie");
	static const LPCTSTR bt_chrome = TEXT("chrome");
	static const LPCTSTR bt_firefox = TEXT("firefox");
	static const LPCTSTR bt_iecm = TEXT("iecm");




	CommentViewProperty::CommentViewProperty():
	commentFoldingFlag(TRUE),
		commentTimeType(StreamingTimeType),
		baseStringColor(PALETTERGB(0,0,0)),
		backColor(PALETTERGB(255,255,255)),
		selectBackColor(PALETTERGB(255,240,240)),			
		selectSellLineColor(PALETTERGB(255,0,0)),						
		normalSellLineColor( PALETTERGB(0,0,0)),
		colLineColor(PALETTERGB(224,224,224)),
		linkStringColor(PALETTERGB(30,140,255)),
		ownerStringColor(PALETTERGB(255,0,0))

	{
		for(INT_PTR orderIndex = 0;orderIndex < ARRAY_LENGTH(headerOrderArray);orderIndex++){

			new(&headerOrderArray[orderIndex]) INT_PTR(orderIndex);

		}

		memset(headerholSize,-1,sizeof(headerholSize));
	}




	CommentReadProperty::CommentReadProperty():
	commentReadFlag(FALSE),
		ngWordReadFlag(TRUE),
		ngUserReadFlag(TRUE),
		administratorCommentReadFlag(TRUE),
		bspReadFlag(TRUE),
		userCommentReadFlag(TRUE),
		teropReadFlag(TRUE)
	{}




	GeneralProperty::GeneralProperty():
	userCountUpdateFlag(TRUE),
		commentLogAutoSaveFlag(FALSE),
		defaultBrowserFlag(TRUE),
		autoNameRegisterFlag(FALSE),
		autoNameUpdateFlag(FALSE),
		numberNameFlag(FALSE),
		autoColorRegisterFlag(FALSE),
		activeCountTimeFlag(TRUE),
		browserType(BT_INTERNET_EXPLORER),
		ncvUserSettingReadedFlag(FALSE)
	{}



	MainFrameProperty::MainFrameProperty():
	windowFrontFlag(TRUE)
	{

		ZeroMemory(&windowSize,sizeof(windowSize));

	}




	Property::Property()
	{
		TCHAR localAppPath[_MAX_PATH];
		SHGetFolderPathW(0,CSIDL_LOCAL_APPDATA,0,SHGFP_TYPE_CURRENT,localAppPath);

		this->appLocalPath = localAppPath;
	}

	Property::~Property()
	{


	}

	VOID Property::Initialize(){
		this->~Property();
		new(this) Property;

	}

	BROWSERTYPE Property::CookieSetting(){

		CCookieSettingWindow cookieSettingwindow;

		cookieSettingwindow.SetBrowserType(gp.browserType);

		cookieSettingwindow.DoModal();

		this->gp.browserType = cookieSettingwindow.GetBrowserType();


		

		return this->gp.browserType;

	}

	VOID Property::ReadProperty(){

		CreatePropertyFile();
		CAtlFile	propertyFile;
		
		ULONGLONG propertyFileSize;
		
		if(SUCCEEDED(propertyFile.Create(propertyPath,GENERIC_READ,FILE_SHARE_READ,OPEN_ALWAYS)) == FALSE || SUCCEEDED(propertyFile.GetSize(propertyFileSize)) == FALSE){

			throw Exception(TEXT("設定ファイルが開けませんでした。このエラーが続くようであれば、一度設定ファイルを削除して再度試してみてください"),__LINE__,TEXT(__FILE__),TEXT(__FUNCTION__));

		} 

		std::vector<char> propertyBuf(static_cast<UINT_PTR>(propertyFileSize / sizeof(char) + (1 * sizeof(char))));
		
		
		propertyFile.Read(&propertyBuf[0],propertyBuf.size());
		
		LPSTR propertyTagStart = strstr(&propertyBuf[0],"<");
		if(propertyTagStart != NULL){
			ReadPropertyXML reader(*this);
			reader.Parse(propertyTagStart);
		}


		

		return;
	}


	VOID Property::CreatePropertyFile(){

		CString iniFile;
		iniFile = appLocalPath;
		iniFile += TEXT("\\qwerty_nico\\nlite.ini");
		SurelyCreate(iniFile,TRUE);
		

		TCHAR propertyBuf[_MAX_PATH];
		LPCTSTR sectionName = TEXT("property");
		LPCTSTR keyName = TEXT("dir");
		::GetPrivateProfileString(sectionName,keyName,TEXT(""),propertyBuf,ARRAY_LENGTH(propertyBuf),iniFile);

		if((_tcslen(propertyBuf) == 0) || !((PathFileExists(propertyBuf) &&  !::PathIsDirectory( propertyBuf )))){
			
			propertyFolderPath = appLocalPath;
			propertyFolderPath += TEXT("\\qwerty_nico\\");
			
			::WritePrivateProfileString(sectionName,keyName,propertyFolderPath,iniFile);
			
		} else {
			propertyFolderPath = propertyBuf;

		}
		propertySaveFolderPath = propertyFolderPath;
		propertySaveFolderPath += TEXT("nlite\\");
		propertyPath = propertySaveFolderPath;
		propertyPath += TEXT("property.xml");
		listenerDataPath = propertySaveFolderPath;
		listenerDataPath += TEXT("listenerData.xml");
		SurelyCreate(propertySaveFolderPath,FALSE);
		SurelyCreate(propertyPath,TRUE);
		SurelyCreate(listenerDataPath,TRUE);
		
		return;
	}


	VOID Property::WriteProperty(){

		CreatePropertyFile();
		CComPtr<IXmlWriter> pWriter;
		CreateXmlWriter(__uuidof(IXmlWriter), reinterpret_cast<void**>(&pWriter), 0);
		
		// XMLファイルパス作成
		TCHAR xml[MAX_PATH];
		_tcscpy(xml,this->propertyPath);



		// ファイルストリーム作成
		CComPtr<IStream> pStream;
		SHCreateStreamOnFile(xml, STGM_CREATE | STGM_WRITE, &pStream);

		pWriter->SetOutput(pStream);
		// インデント有効化
		pWriter->SetProperty(XmlWriterProperty_Indent, TRUE);

		// <?xml version="1.0" encoding="UTF-8"?>
		pWriter->WriteStartDocument(XmlStandalone_Omit);

		pWriter->WriteStartElement(NULL,TEXT("nliteconfig"),NULL);
		//コメント読み上げ設定書き込み
		NLITE_XMLELLMENT_WRITE(pWriter,crp);
		NLITE_ELLEMENT_WRITE_STR(pWriter,crp.outString);
		NLITE_ELLEMENT_WRITE_INT(pWriter,crp.administratorCommentReadFlag);
		NLITE_ELLEMENT_WRITE_INT(pWriter,crp.besideLengthFlag);
		NLITE_ELLEMENT_WRITE_INT(pWriter,crp.bspReadFlag);
		NLITE_ELLEMENT_WRITE_INT(pWriter,crp.commentReadFlag);
		NLITE_ELLEMENT_WRITE_INT(pWriter,crp.maxCommentLength);
		NLITE_ELLEMENT_WRITE_INT(pWriter,crp.newLineReadFlag);
		NLITE_ELLEMENT_WRITE_INT(pWriter,crp.ngUserReadFlag);
		NLITE_ELLEMENT_WRITE_INT(pWriter,crp.ngWordReadFlag);
		NLITE_ELLEMENT_WRITE_STR(pWriter,crp.shortComment);
		NLITE_ELLEMENT_WRITE_INT(pWriter,crp.teropReadFlag);
		NLITE_ELLEMENT_WRITE_INT(pWriter,crp.userCommentReadFlag);
		pWriter->WriteEndElement();
		//commentview設定値書き込み
		NLITE_XMLELLMENT_WRITE(pWriter,cvp);
		NLITE_XML_WRITE_FOR_INT(pWriter,cvp.headerholSize);
		NLITE_ELLEMENT_WRITE_INT(pWriter,cvp.anonymousIDLinkColor);
		NLITE_ELLEMENT_WRITE_INT(pWriter,cvp.backColor);
		NLITE_ELLEMENT_WRITE_INT(pWriter,cvp.baseStringColor);
		NLITE_ELLEMENT_WRITE_INT(pWriter,cvp.commentFoldingFlag);
		NLITE_ELLEMENT_WRITE_INT(pWriter,cvp.commentTimeType);
		NLITE_XML_WRITE_FOR_INT(pWriter,cvp.headerOrderArray);
		NLITE_ELLEMENT_WRITE_INT(pWriter,cvp.linkStringColor);
		NLITE_ELLEMENT_WRITE_INT(pWriter,cvp.selectBackColor);
		NLITE_ELLEMENT_WRITE_INT(pWriter,cvp.selectSellLineColor);
		NLITE_ELLEMENT_WRITE_INT(pWriter,cvp.colLineColor);
		NLITE_ELLEMENT_WRITE_INT(pWriter,cvp.normalSellLineColor);
		NLITE_ELLEMENT_WRITE_INT(pWriter,cvp.ownerStringColor);
		
		pWriter->WriteEndElement();


		NLITE_XMLELLMENT_WRITE(pWriter,mfp);
		NLITE_ELLEMENT_WRITE_INT(pWriter,mfp.windowSize.cx);
		NLITE_ELLEMENT_WRITE_INT(pWriter,mfp.windowSize.cy);
		NLITE_ELLEMENT_WRITE_INT(pWriter,mfp.windowFrontFlag);
		pWriter->WriteEndElement();


		//共通設定書き込み
		NLITE_XMLELLMENT_WRITE(pWriter,gp);
		NLITE_ELLEMENT_WRITE_INT(pWriter,gp.activeCountTimeFlag);
		NLITE_ELLEMENT_WRITE_INT(pWriter,gp.autoColorRegisterFlag);
		NLITE_ELLEMENT_WRITE_INT(pWriter,gp.autoNameUpdateFlag);
		NLITE_ELLEMENT_WRITE_INT(pWriter,gp.autoNameRegisterFlag);
		NLITE_ELLEMENT_WRITE_STR(pWriter,gp.browserPath);
		NLITE_ELLEMENT_WRITE_INT(pWriter,gp.browserType);
		NLITE_ELLEMENT_WRITE_INT(pWriter,gp.commentLogAutoSaveFlag);
		NLITE_ELLEMENT_WRITE_STR(pWriter,gp.commentPath);
		NLITE_ELLEMENT_WRITE_INT(pWriter,gp.defaultBrowserFlag);
		NLITE_ELLEMENT_WRITE_INT(pWriter,gp.numberNameFlag);
		NLITE_ELLEMENT_WRITE_INT(pWriter,gp.userCountUpdateFlag);
		NLITE_ELLEMENT_WRITE_INT(pWriter,gp.ncvUserSettingReadedFlag);
		
		pWriter->WriteEndElement();
		pWriter->WriteEndDocument();

		pWriter->Flush();

		return;
	}


	///
	///コンストラクタ
	///
	ReadPropertyXML::ReadPropertyXML(Property &in_property):nliteProperty(in_property),propertyType(Node::None){

		return;
	}



	//
	//設定ファイル解析処理
	//

#define NLITE_PSZNAME_CMP(t,p) (_tcscmp(NLITE_GET_TYPENAME(t),(LPCTSTR)(p)) == 0)
	void ReadPropertyXML::OnStartElement (const XML_Char *pszName, const XML_Char **papszAttrs){

		switch(propertyType){

		case Node::None:

			if(NLITE_PSZNAME_CMP(nliteProperty.crp,pszName)){

				propertyType = Node::CommentReadProperty;

			} else if(NLITE_PSZNAME_CMP(nliteProperty.cvp,pszName)){

				propertyType = Node::CommentViewProperty;

			} else if(NLITE_PSZNAME_CMP(nliteProperty.mfp,pszName)){

				propertyType = Node::MainFrameProperty;

			} else if(NLITE_PSZNAME_CMP(nliteProperty.gp,pszName)){

				propertyType = Node::GeneralProperty;

			}

			break;


		case Node::CommentReadProperty:
		case Node::CommentViewProperty:
		case Node::GeneralProperty:
		case Node::MainFrameProperty:

			nodeName = (LPCTSTR)pszName;
			break;

		default:

			break;
		}

		return;
	}




	void ReadPropertyXML::OnEndElement (const XML_Char *pszName){

		if(NLITE_PSZNAME_CMP(nliteProperty.crp,pszName) || 
			NLITE_PSZNAME_CMP(nliteProperty.cvp,pszName)||
			NLITE_PSZNAME_CMP(nliteProperty.gp,pszName) || 
			NLITE_PSZNAME_CMP(nliteProperty.mfp,pszName)){

				propertyType = Node::None;

		}
		nodeName = TEXT("");

		return;
	}

#define NLITE_R_X_P_S(p,p2,v) \
	if(_tcscmp(TEXT(#v),nodeName.c_str()) == 0){\
	_tcsncpy(p.p2.v,(LPCTSTR)pszData,nLength);\
	break;\
	}

#define NLITE_R_X_P_I(p,p2,v) \
	if(_tcscmp(TEXT(#v),nodeName.c_str()) == 0){\
	p.p2.v = 0;\
	strToIntN(p.p2.v,pszData,nLength);\
	break;\
	}

#define NLITE_RXP_AI(p,p2,v) {\
	TCHAR name[LENGTH_256];\
	for(INT_PTR index = 0;index < ARRAY_LENGTH(p.p2.v);index++){\
	_stprintf(name,TEXT("%s%d"),TEXT(#v),index);\
	if(_tcscmp(name,nodeName.c_str()) == 0){\
	p.p2.v[index] = 0;\
	strToIntN(p.p2.v[index],pszData,nLength);\
	goto end;\
	}\
	}\
	}

#define NLITE_NAME(n) (#n)

	void ReadPropertyXML::OnCharacterData (const XML_Char *pszData, int nLength){

		if (nodeName.empty() == true)return;

		switch(propertyType){



		case Node::CommentReadProperty:

			NLITE_R_X_P_S(nliteProperty,crp,shortComment);
			NLITE_R_X_P_I(nliteProperty,crp,administratorCommentReadFlag);
			NLITE_R_X_P_I(nliteProperty,crp,besideLengthFlag);
			NLITE_R_X_P_I(nliteProperty,crp,bspReadFlag);
			NLITE_R_X_P_I(nliteProperty,crp,commentReadFlag);
			NLITE_R_X_P_I(nliteProperty,crp,maxCommentLength);
			NLITE_R_X_P_I(nliteProperty,crp,newLineReadFlag);
			NLITE_R_X_P_I(nliteProperty,crp,ngUserReadFlag);
			NLITE_R_X_P_I(nliteProperty,crp,ngWordReadFlag);
			NLITE_R_X_P_S(nliteProperty,crp,outString);
			NLITE_R_X_P_S(nliteProperty,crp,shortComment);
			NLITE_R_X_P_I(nliteProperty,crp,teropReadFlag);
			NLITE_R_X_P_I(nliteProperty,crp,userCommentReadFlag);

			break;
		case Node::CommentViewProperty:
			NLITE_R_X_P_I(nliteProperty,cvp,anonymousIDLinkColor);
			NLITE_R_X_P_I(nliteProperty,cvp,backColor);
			NLITE_R_X_P_I(nliteProperty,cvp,baseStringColor);
			NLITE_R_X_P_I(nliteProperty,cvp,commentFoldingFlag);
			NLITE_R_X_P_I(nliteProperty,cvp,commentTimeType);
			NLITE_R_X_P_I(nliteProperty,cvp,linkStringColor);
			NLITE_RXP_AI(nliteProperty,cvp,headerholSize);
			NLITE_RXP_AI(nliteProperty,cvp,headerOrderArray);
			NLITE_R_X_P_I(nliteProperty,cvp,selectBackColor);
			NLITE_R_X_P_I(nliteProperty,cvp,selectSellLineColor);
			NLITE_R_X_P_I(nliteProperty,cvp,normalSellLineColor);
			NLITE_R_X_P_I(nliteProperty,cvp,colLineColor);
			NLITE_R_X_P_I(nliteProperty,cvp,ownerStringColor);
			
			break;
		case Node::GeneralProperty:
			NLITE_R_X_P_I(nliteProperty,gp,activeCountTimeFlag);
			NLITE_R_X_P_I(nliteProperty,gp,autoColorRegisterFlag);
			NLITE_R_X_P_I(nliteProperty,gp,autoNameRegisterFlag);
			NLITE_R_X_P_I(nliteProperty,gp,autoNameUpdateFlag);
			NLITE_R_X_P_S(nliteProperty,gp,browserPath);
			NLITE_R_X_P_I(nliteProperty,gp,browserType);
			NLITE_R_X_P_I(nliteProperty,gp,commentLogAutoSaveFlag);
			NLITE_R_X_P_S(nliteProperty,gp,commentPath);
			NLITE_R_X_P_I(nliteProperty,gp,defaultBrowserFlag);
			NLITE_R_X_P_I(nliteProperty,gp,numberNameFlag);
			NLITE_R_X_P_I(nliteProperty,gp,userCountUpdateFlag);
			NLITE_R_X_P_I(nliteProperty,gp,ncvUserSettingReadedFlag);
			break;
		case Node::MainFrameProperty:
			NLITE_R_X_P_I(nliteProperty,mfp,windowSize.cx);
			NLITE_R_X_P_I(nliteProperty,mfp,windowSize.cy);
			NLITE_R_X_P_I(nliteProperty,mfp,windowFrontFlag);
			break;


		default:

			break;


		}

end:

		return;
	}





}