#include <common/opendlg.hpp>
#include <common/guiwnd.hpp>
#include <common/StringBuffer.hpp>

OpenDialog::OpenDialog(void)
{
	setZero();
	setLength();
}

OpenDialog::OpenDialog(const OpenDialog &someOpenDialog)
{
	setLength();
	*this=someOpenDialog;
}

OpenDialog::~OpenDialog()
{
}

OpenDialog &OpenDialog::operator=(const OpenDialog &someOpenDialog)
{
	owner(someOpenDialog.owner());
	instance(someOpenDialog.instance());
	filter(someOpenDialog.filter());
  filterPattern(someOpenDialog.filterPattern());
	customFilter(someOpenDialog.customFilter());
	filterIndex(someOpenDialog.filterIndex());
	fileName(someOpenDialog.fileName());
	fileTitle(someOpenDialog.fileTitle());
	initialDirectory(someOpenDialog.initialDirectory());
	title(someOpenDialog.title());
	creationFlags(someOpenDialog.creationFlags());
	defaultExtension(someOpenDialog.defaultExtension());
	return *this;
}

BOOL OpenDialog::operator==(const OpenDialog &someOpenDialog)const
{
	return (owner()==someOpenDialog.owner()&&
					instance()==someOpenDialog.instance()&&
					filter()==someOpenDialog.filter()&&
          filterPattern()==someOpenDialog.filterPattern()&&
					customFilter()==someOpenDialog.customFilter()&&
					filterIndex()==someOpenDialog.filterIndex()&&
					fileName()==someOpenDialog.fileName()&&
					fileTitle()==someOpenDialog.fileTitle()&&
					initialDirectory()==someOpenDialog.initialDirectory()&&
					title()==someOpenDialog.title()&&
					creationFlags()==someOpenDialog.creationFlags()&&
          defaultExtension()==someOpenDialog.defaultExtension());
}

HWND OpenDialog::owner(void)const
{
  return OPENFILENAME::hwndOwner;
}

void OpenDialog::owner(HWND hwndOwner)
{
  OPENFILENAME::hwndOwner=hwndOwner;
}

HINSTANCE OpenDialog::instance(void)const
{
	return OPENFILENAME::hInstance;
}

void OpenDialog::instance(HINSTANCE hInstance)
{
	OPENFILENAME::hInstance=hInstance;
}

const String &OpenDialog::filter(void)const
{
	return mFilter;
}

void OpenDialog::filter(const String &filter)
{
  mFilter=filter;
}

const String &OpenDialog::filterPattern(void)const
{
	return mFilterPattern;
}

void OpenDialog::filterPattern(const String &filterPattern)
{
  mFilterPattern=filterPattern;
}

const String &OpenDialog::customFilter(void)const
{
	return mCustomFilter;
}

void OpenDialog::customFilter(const String &customFilter)
{
	mCustomFilter=customFilter;
}

DWORD OpenDialog::filterIndex(void)const
{
	return OPENFILENAME::nFilterIndex;
}

void OpenDialog::filterIndex(DWORD filterIndex)
{
  OPENFILENAME::nFilterIndex=filterIndex;
}

const String &OpenDialog::fileName(void)const
{
	return mFileName;
}

void OpenDialog::fileName(const String &fileName)
{
  mFileName=fileName;
}

const String &OpenDialog::fileTitle(void)const
{
	return mFileTitle;
}

void OpenDialog::fileTitle(const String &fileTitle)
{
  mFileTitle=fileTitle;
}

const String &OpenDialog::initialDirectory(void)const
{
	return mInitialDirectory;
}

void OpenDialog::initialDirectory(const String &initialDirectory)
{
  mInitialDirectory=initialDirectory;
}

const String &OpenDialog::title(void)const
{
	return mTitle;
}

void OpenDialog::title(const String &title)
{
	mTitle=title;
}

DWORD OpenDialog::creationFlags(void)const
{
	return OPENFILENAME::Flags;
}

void OpenDialog::creationFlags(DWORD creationFlags)
{
  OPENFILENAME::Flags=creationFlags;
}

const String &OpenDialog::defaultExtension(void)const
{
  return mDefaultExtension;
}

void OpenDialog::defaultExtension(const String &defaultExtension)
{
  mDefaultExtension=defaultExtension;
}

const String &OpenDialog::templateName(void)const
{
  return mTemplateName;
}

void OpenDialog::templateName(const String &templateName)
{
  if(templateName.isNull())return;
	mTemplateName=templateName;
	OPENFILENAME::lpTemplateName=(char*)mTemplateName;
}

LPOFNHOOKPROC OpenDialog::hookProc(void)const
{
  return OPENFILENAME::lpfnHook;
}

void OpenDialog::hookProc(LPOFNHOOKPROC pHookProc)
{
  OPENFILENAME::lpfnHook=pHookProc;
}

DWORD OpenDialog::customData(void)const
{
  return OPENFILENAME::lCustData;
}

void OpenDialog::customData(DWORD customData)
{
  OPENFILENAME::lCustData=customData;
}

void OpenDialog::setZero(void)
{
	 ::memset(&((OPENFILENAME&)*this),0,sizeof(OPENFILENAME));
}

void OpenDialog::setLength(void)
{
	OPENFILENAME::lStructSize=sizeof(OPENFILENAME);
}

BOOL OpenDialog::getSaveFileName(GUIWindow &parentWindow,const String &filterPatternString,const String &titleString,const String &fileTitleString,String &pathFileName)
{
  owner(parentWindow);
	return getSaveFileName(filterPatternString,titleString,fileTitleString,pathFileName);
}

BOOL OpenDialog::getOpenFileName(GUIWindow &parentWindow,const String &filterPatternString,const String &titleString,const String &fileTitleString,String &pathFileName)
{
  owner(parentWindow);
	return getOpenFileName(filterPatternString,titleString,fileTitleString,pathFileName);
}

BOOL OpenDialog::getSaveFileName(const String &filterPatternString,const String &titleString,const String &fileTitleString,String &pathFileName)
{
  String filterString;

	if(filterPatternString.isNull()||titleString.isNull())return FALSE;
	filter(filterPatternString);
	if(filterString.isNull()){filterString=fileTitleString.betweenString('.',0);filterString.insert("*.");}
	filterPattern(filterString);
	instance((HINSTANCE)0);
	hookProc(0);
	customData(0);
	if(fileTitleString.isNull())fileName(filterPatternString);
	else fileName(fileTitleString);
	title(titleString);
	fileTitle(titleString);
	creationFlags(OpenDialog::EXPLORER|OpenDialog::OVERWRITEPROMPT|OpenDialog::PATHMUSTEXIST);
  if(!getSaveFileName())return FALSE;
	pathFileName=fileName();
  return TRUE;
}

BOOL OpenDialog::getOpenFileName(const String &filterPatternString,const String &titleString,const String &fileTitleString,String &pathFileName)
{
  String filterString;

	if(filterPatternString.isNull()||titleString.isNull())return FALSE;
	filterString=filterPatternString.betweenString('.',0);
	instance((HINSTANCE)0);
	hookProc(0);
	customData(0);
	filter(filterString);
	filterPattern(filterPatternString);
	if(fileTitleString.isNull())fileName(filterPatternString);
	else fileName(fileTitleString);
	title(titleString);
	fileTitle(titleString);
	creationFlags(creationFlags()|OpenDialog::EXPLORER|OpenDialog::PATHMUSTEXIST|OpenDialog::FILEMUSTEXIST);
	if(!getOpenFileName())return FALSE;
	pathFileName=fileName();
  return TRUE;
}

BOOL OpenDialog::getOpenFileName(const String &filterPatternString,const String &titleString,const String &fileTitleString,Block<String> &strFileNames)
{
  String filterString;
	String strPath;
	String strPathFileName;
	char *ptrString;

  strFileNames.remove();
	if(filterPatternString.isNull()||titleString.isNull())return FALSE;
	filterString=filterPatternString.betweenString('.',0);
	instance((HINSTANCE)0);
	hookProc(0);
	customData(0);
	filter(filterString);
	filterPattern(filterPatternString);
	if(fileTitleString.isNull())fileName(filterPatternString);
	else fileName(fileTitleString);
	title(titleString);
	fileTitle(titleString);
	creationFlags(OpenDialog::ALLOWMULTISELECT|OpenDialog::EXPLORER|OpenDialog::PATHMUSTEXIST);
	mFileNameBuffer.reserve(MaxMultiSelect);
	if(!getOpenFileName())return FALSE;
	ptrString=mFileNameBuffer;
	if(!ptrString)return FALSE;
	strPath=ptrString;
	if(strPath.strstr(".")){strFileNames.insert(&strPath);return TRUE;}
	while(TRUE)
	{
	  while(*ptrString)ptrString++;
		if(!*(++ptrString))break;
		strPathFileName=strPath+String("\\");
		strPathFileName+=ptrString;
		strFileNames.insert(&strPathFileName);
	}
	return (strFileNames.size()?TRUE:FALSE);
}

BOOL OpenDialog::getOpenFileName(void)
{
	String filterPattern;
	WORD returnCode;

  mFileNameBuffer.reserve(MaxLength);
	mFileTitleBuffer.reserve(MaxTitle);
	if(mFilter.isNull()||mFilterPattern.isNull())OPENFILENAME::lpstrFilter=0;
	else
	{
		long lengthFilter(mFilter.length());
		long lengthPattern(mFilterPattern.length());
		filterPattern.reserve(lengthFilter+lengthPattern+3);
		::memcpy((LPSTR)filterPattern,(LPSTR)mFilter,lengthFilter);
		((LPSTR)filterPattern)[lengthFilter]=0;
		::memcpy(((LPSTR)filterPattern)+lengthFilter+1,(LPSTR)mFilterPattern,lengthPattern);
		((LPSTR)filterPattern)[lengthFilter+lengthPattern+1]=0;
		((LPSTR)filterPattern)[lengthFilter+lengthPattern+2]=0;
		OPENFILENAME::lpstrFilter=(LPSTR)filterPattern;
	}
	OPENFILENAME::lpstrCustomFilter=0;
	OPENFILENAME::nMaxCustFilter=0;
	if(OPENFILENAME::lpstrFilter)OPENFILENAME::nFilterIndex=1;
	else OPENFILENAME::nFilterIndex=0;
  ::memcpy((LPSTR)mFileNameBuffer,(LPSTR)mFileName,mFileName.length());
	OPENFILENAME::lpstrFile=(LPSTR)mFileNameBuffer;
	OPENFILENAME::nMaxFile=mFileNameBuffer.lengthBytes();
	::memcpy((LPSTR)mFileTitleBuffer,(LPSTR)mFileTitle,mFileTitle.length());
	OPENFILENAME::lpstrFileTitle=(LPSTR)mFileTitleBuffer;
	OPENFILENAME::nMaxFileTitle=mFileTitleBuffer.lengthBytes();
	if(mInitialDirectory.isNull())OPENFILENAME::lpstrInitialDir=0;
	else OPENFILENAME::lpstrInitialDir=(LPSTR)mInitialDirectory;
	if(mTitle.isNull())OPENFILENAME::lpstrTitle=0;
	else OPENFILENAME::lpstrTitle=(LPSTR)mTitle;
	OPENFILENAME::Flags=creationFlags();
	if(!mFileNameBuffer.isNull())
	{
		int stringPos(mFileNameBuffer.strpos("."));
		OPENFILENAME::nFileExtension=stringPos-1;
		char *lpStr=(LPSTR)mFileNameBuffer;
		while(lpStr[stringPos]!='\\'&&lpStr[stringPos]!='/'&&lpStr[stringPos]!=':'&&stringPos>=0)stringPos--;
		OPENFILENAME::nFileOffset=stringPos+1;
	}
	if(!mDefaultExtension.isNull())OPENFILENAME::lpstrDefExt=(LPSTR)mDefaultExtension;
	else OPENFILENAME::lpstrDefExt=0;
	returnCode=::GetOpenFileName(&((OPENFILENAME&)*this));
	if(returnCode)
	{
	  parseFileNames(mFileNameBuffer,mFileNames);
		if(mFileNames.size())mFileName=mFileNames[0];
		mFileTitle=mFileTitleBuffer;
	}
	return returnCode;
}

BOOL OpenDialog::getSaveFileName(void)
{
	String filterPattern;
	String fileName;
  String fileTitle;
	WORD returnCode;

	fileName.reserve(MaxSaveLength);
  fileTitle.reserve(MaxTitle);
	if(mFilter.isNull()||mFilterPattern.isNull())OPENFILENAME::lpstrFilter=0;
	else
	{
		long lengthFilter(mFilter.length());
		long lengthPattern(mFilterPattern.length());
		filterPattern.reserve(lengthFilter+lengthPattern+3);
		::memcpy((LPSTR)filterPattern,(LPSTR)mFilter,lengthFilter);
		((LPSTR)filterPattern)[lengthFilter]=0;
		::memcpy(((LPSTR)filterPattern)+lengthFilter+1,(LPSTR)mFilterPattern,lengthPattern);
		((LPSTR)filterPattern)[lengthFilter+lengthPattern+1]=0;
		((LPSTR)filterPattern)[lengthFilter+lengthPattern+2]=0;
		OPENFILENAME::lpstrFilter=(LPSTR)filterPattern;
	}
	OPENFILENAME::lpstrCustomFilter=0;
	OPENFILENAME::nMaxCustFilter=0;
	if(OPENFILENAME::lpstrFilter)OPENFILENAME::nFilterIndex=1;
	else OPENFILENAME::nFilterIndex=0;
	::memcpy((LPSTR)fileName,(LPSTR)mFileName,mFileName.length());
	OPENFILENAME::lpstrFile=(LPSTR)fileName;
	OPENFILENAME::nMaxFile=MaxSaveLength;
	::memcpy((LPSTR)fileTitle,(LPSTR)mFileTitle,mFileTitle.length());
	OPENFILENAME::lpstrFileTitle=(LPSTR)fileTitle;
	OPENFILENAME::nMaxFileTitle=MaxTitle;
	if(mInitialDirectory.isNull())OPENFILENAME::lpstrInitialDir=0;
	else OPENFILENAME::lpstrInitialDir=(LPSTR)mInitialDirectory;
	if(mTitle.isNull())OPENFILENAME::lpstrTitle=0;
	else OPENFILENAME::lpstrTitle=(LPSTR)mTitle;
	OPENFILENAME::Flags=creationFlags();
	if(!fileName.isNull())
	{
		int stringPos(fileName.strpos("."));
		OPENFILENAME::nFileExtension=stringPos-1;
		char *lpStr=(LPSTR)fileName;
		while(lpStr[stringPos]!='\\'&&lpStr[stringPos]!='/'&&lpStr[stringPos]!=':'&&stringPos>=0)stringPos--;
		OPENFILENAME::nFileOffset=stringPos+1;
	}
	if(!mDefaultExtension.isNull())OPENFILENAME::lpstrDefExt=(LPSTR)mDefaultExtension;
	else OPENFILENAME::lpstrDefExt=0;
	OPENFILENAME::lpfnHook=0;
	returnCode=::GetSaveFileName(&((OPENFILENAME&)*this));
	if(returnCode)
	{
		mFileName=fileName;
		mFileTitle=fileTitle;
	}
	return returnCode;
}

void OpenDialog::parseFileNames(const String &nameBuffer,Block<String> &fileNames)
{
  String directoryName;
	String item;
	int index;
	bool isFirst;

	index=0;
	isFirst=true;
	fileNames.remove();
  if(!(creationFlags()&ALLOWMULTISELECT))
	{
	  fileNames.insert(&nameBuffer);
		return;
  }
  while(true)
	{
    item=parseLine(index,nameBuffer);
		if(item.isNull())break;
		if(isFirst)
		{
		  isFirst=false;
			directoryName=item;
		}
		else fileNames.insert(&String(directoryName+"\\"+item));
	}
	if(!fileNames.size())fileNames.insert(&directoryName);
}

String OpenDialog::parseLine(int &index,const String &strLine)
{
  StringBuffer sb;
  while(strLine[index]!=0)
	{
	  sb.append(strLine[index]);
		index++;
	}
	index++;
	return sb.toString();
}
