#include "stdafx.h"
#include "nlite_include.h"



namespace nlite{

	namespace nliteregex{
		namespace text{
			const  CString URL_TEXT = TEXT("(https?|ftp)(://[-_.!~*\'()a-zA-Z0-9;/?:@&=+$,%#]+)");
			const  CString TAG_TEXT = TEXT("<[\"_;!?,\\:.'$%&#/a-zA-Z0-9= ]*>");
			const  CString VIDEOID_TEXT = TEXT("(sm|nm)([0-9])+");
			const  CString LIVEID_TEXT = TEXT("(lv)([0-9])+");
			const  CString LINK_TEXT = TEXT("(") + URL_TEXT + TEXT(")|(") + VIDEOID_TEXT + TEXT(")|(") + LIVEID_TEXT + TEXT(")");
			const  CString SEARTCH_AT_MARK(TEXT("(.*)(@|＠)([^ |^　][^@^＠]+)"));
			const  tstring NUTHINGSTRING(TEXT(""));
		}
		const  tregex URL(text::URL_TEXT);
		const  tregex TAGSTRING(text::TAG_TEXT);
		const  tregex VIDEOID(text::VIDEOID_TEXT);
		const  tregex LIVEID(text::LIVEID_TEXT);
		const  tregex LILNKREGEX(text::LINK_TEXT);
		const tregex NAMESERTCHREGEX(text::SEARTCH_AT_MARK);
	}
	Property nliteProperty;	
	CListenerList nlite::listenerList;
	TCHAR appFolderPath[_MAX_PATH];
	CString ncvAppSettingPath;
	TCHAR localAppDataPath[_MAX_PATH];
	speaker::ISpeaker &g_speaker = speaker::ISpeaker::GetMeiNormal(TEXT("libs\\Voice\\mei_normal\\"),TEXT("libs\\open_jtalk_dic\\"));
	VOID nlite::UnexpectedErrorMessageShow(LPCTSTR headMessage,LPCTSTR summary,UINT line,LPCTSTR fileName,LPCTSTR function){
		
		CString errLogFilePath(nliteProperty.propertySaveFolderPath);
		CAtlFile errFile;
		TCHAR errfile[_MAX_PATH];

		time_t nowtime = time(NULL);
		tm timestruct = *gmtime(&nowtime);
		_tcsftime(errfile,ARRAY_LENGTH(errfile),TEXT("errorlog\\nlite_errorLog_%Y%m%d%H%M%S.log"),&timestruct);
		errLogFilePath += errfile;
		SurelyCreate(errLogFilePath,TRUE);
		
		CString outputLogfileString;
		TCHAR file[_MAX_PATH];
		TCHAR ext[_MAX_PATH];
		_wsplitpath(fileName,(wchar_t*)NULL,(wchar_t*)NULL,file,ext);
		DWORD lastErrorCode = ::GetLastError();
		LPTSTR lpMsgBuf;
		FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, lastErrorCode,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf,0,(va_list*)NULL);
		
		
		outputLogfileString.Format(TEXT("##ERROR##\r\n発生ファイル名:%s%s\r\n発生関数名:%s\r\n発生行:%d\r\nエラーメッセージ:%s\r\n最終OSエラーコード:%u\r\n最終OSエラーメッセージ:%s")
			,file,ext,function,line,summary,lastErrorCode,lpMsgBuf);
		LocalFree(lpMsgBuf);
		CStringA outputLogfileStringA(outputLogfileString);
		errFile.Create(errLogFilePath,GENERIC_WRITE,0,OPEN_ALWAYS);
		errFile.Write(outputLogfileStringA,outputLogfileStringA.GetLength() * sizeof(char));
		tstring errMessage;
		errMessage = headMessage;
		errMessage += TEXT("想定されていないエラーが発生しました。以下のファイルにエラーファイルが出力されたました。\r\n");
		errMessage += errLogFilePath;
		errMessage += TEXT("\r\nエラーメッセージ:");
		errMessage += summary;
		::MessageBox(NULL,errMessage.c_str(),TEXT("想定されていないエラー"),MB_ICONERROR | MB_OK);
		
		
		
		
		
		return;
	}

	HINSTANCE OpenURL(HWND hwnd,const GeneralProperty &gp,LPCTSTR url ,INT nShowCommand){

		HINSTANCE rslt;

		if(gp.browserPath.Length() == 0){

			rslt = ShellExecute(hwnd, NULL, url, NULL, NULL, nShowCommand);

		} else{

			rslt = ShellExecute(hwnd, NULL, gp.browserPath, url, NULL, nShowCommand);

		}

		return rslt;

	}

	BOOL SurelyCreate(LPCTSTR dir,BOOL bFile){



		BOOL rslt = FALSE;
		std::vector<TCHAR> buf(_tcslen(dir) + 1);
		_tcscpy(&buf[0],dir);


		if( (PathFileExists(dir) && (!bFile || !::PathIsDirectory( dir )))){

			goto success;
		}

		LPTSTR startPtr = &buf[0];
		LPTSTR indexPtr = startPtr;
		LPTSTR cmpPtr;
		do {

			cmpPtr = _tcsstr(indexPtr,TEXT("\\"));

			if(cmpPtr == NULL){

				if(bFile == TRUE){
					CAtlFile file;
					if( file.Create(startPtr,0,0,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL) != S_OK){

						goto err;

					}
				} else {

					::CreateDirectory(startPtr,0);
				}

				break;


			}else if(indexPtr == cmpPtr){
				break;

			}

			cmpPtr[0] = TEXT('\0');
			::CreateDirectory(startPtr,0);
			cmpPtr[0] = TEXT('\\');
			cmpPtr++;
			indexPtr = cmpPtr;


		}while(indexPtr[0] != TEXT('\0'));

success:


		rslt = TRUE;

end:

		return rslt;


err:
		rslt = FALSE;
		goto end;
	}


	///
	///NCVユーザ情報ファイルパス取得XMLパーサ
	///
	class CReadNCVListenerInfoFile:public CXmlParser{

	private:

		BOOL settingDirFlag;
		CString &path;	




	public:

		CReadNCVListenerInfoFile(CString &in_path):settingDirFlag(FALSE),path(in_path){}

		void OnStartElement (const XML_Char *pszName, const XML_Char **papszAttrs){

			if(_tcscmp(pszName,TEXT("SettingDir")) == 0){

				settingDirFlag = TRUE;

			}

		}

		void OnEndElement (const XML_Char *pszName){

			if(_tcscmp(pszName,TEXT("SettingDir")) == 0){

				settingDirFlag = FALSE;

			}

		}

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

			if(settingDirFlag == TRUE){

				path.Append(pszData,nLength);

			}

		}
	};

	CString GetNCVListenerInfoFilePath(){


		CString rslt;


		if((PathFileExists(ncvAppSettingPath) &&  (!::PathIsDirectory( ncvAppSettingPath )))){


			CAtlFile ncvAppSettingFile;
			ULONGLONG ncvAppSettingFileSize = 0;
			if(SUCCEEDED(ncvAppSettingFile.Create(ncvAppSettingPath,GENERIC_READ,FILE_SHARE_READ,OPEN_ALWAYS)) == FALSE ||
				SUCCEEDED(ncvAppSettingFile.GetSize(ncvAppSettingFileSize)) == FALSE){

					throw Exception(TEXT("NCVの設定ファイルが読み込めませんでした"),__LINE__,TEXT(__FILE__),TEXT(__FUNCTION__));

			}
			std::vector<char> fileBuf(static_cast<UINT_PTR>(ncvAppSettingFileSize) / sizeof(char) + (1 * sizeof(char)));
			ncvAppSettingFile.Read(&fileBuf[0],fileBuf.size());
			LPSTR startPtr = strstr(&fileBuf[0],"<");
			if(startPtr != NULL){
				CReadNCVListenerInfoFile parser(rslt);
				parser.Parse(startPtr);
				rslt += TEXT("UserSetting.xml");

			}

		}




		return rslt;
	}



	const CApplicationInfo * appInfo = NULL;

}

