/*------------------------------------------------------------------------------*
 * File Name:	FileList.h 														*
 * Creation: 	Frank															*
 * Purpose: OriginC Source C file												*
 * Copyright (c) Originlab Corp.	2006										*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	AW 03/09/06 ADD_RECENT_FILE_LIST_CLASS										*
 *	CPY 4/28/06 MRF_ON_POPUP_MENU												*
 *------------------------------------------------------------------------------*/

/// AW 03/09/06 ADD_RECENT_FILE_LIST_CLASS
#ifndef _FILE_LIST_H
#define _FILE_LIST_H
/// END ADD_RECENT_FILE_LIST_CLASS
#include <origin.h>

#define MAX_RECENT_FILE_NUMBER				10		/// AW 03/09/06 ADD_RECENT_FILE_LIST_CLASS


#define	STRING_LIST_SETTING_FILE		GetAppPath() + STR_ORIGIN_INI_FILE_NAME
#define	FILE_LIST_PREFIX				"List"
/**
#include <..\originlab\FileList.h>

void test_stringList()
{
	FileList sl("ThemeList","X-Functions");
	FileList sl1("ThemeList2","X-Functions" ,11);
	
	sl.Add("List1");
	sl.Add("List2");
	sl.Add("List3");
	sl.Add("List4");
	sl.Add("List5");
	sl.Add("List6");
	sl.Add("List7");
	sl.Add("List8");
	sl.Add("List9");
	sl.Add("List0");
	sl.Add("List11");
	sl.Add("List12");
	sl.Add("List12");
	string strListItem = sl.Get();
	ASSERT(lstrcmp ( strListItem , "List12") == 0);
	string strListItem1 = sl.Get(1);
	ASSERT(lstrcmp ( strListItem1 , "List11") == 0);
	string strListItem2 = sl.Get(2);
	ASSERT(lstrcmp ( strListItem2 , "List0") == 0);
	
	string strFullFilePath=okutil_get_origin_path(ORIGIN_PATH_USER, "X-Functions\Signal Processing") + "Interpolate.OXF";

	sl.Add(strFullFilePath);
	///Remove verbose information test, it should remove category and user infor.
	string strDis = sl.GetDisplayName(0);
	//ASSERT(lstrcmp ( strDis , "User: (Signal Processing) Interpolate") == 0);
	ASSERT(lstrcmp ( strDis , "Interpolate") == 0);
	out_str(strDis);
	
	///Not remove verbose information test, it should keep all infor.
	strDis = sl.GetDisplayName(0, false);
	ASSERT(lstrcmp ( strDis , "User: (Signal Processing) Interpolate") == 0);
	out_str(strDis);
	
	strFullFilePath=okutil_get_origin_path(ORIGIN_PATH_SYSTEM, "X-Functions\Signal Processing") + "Interpolate.OXF";
	sl.Add(strFullFilePath);
	strDis = sl.GetDisplayName(0);
	
	ASSERT(lstrcmp ( strDis , "System:  Interpolate") == 0);
	out_str(strDis);

	strDis = sl.GetDisplayName(0, false);
	ASSERT(lstrcmp ( strDis , "System: (Signal Processing) Interpolate") == 0);
	out_str(strDis);

	ASSERT(sl.GetSize() == 10);
	ASSERT(sl1.GetSize() == 0);
	
	sl1.SetMaxSize(12);
	ASSERT(sl1.GetSize() == 0);
	
	
}
*/

class FileList
{
public:
	void	FileList();
	void	FileList(LPCSTR lpcstrListName,LPCSTR lpcstrSubPath,  int nListSize = MAX_RECENT_FILE_NUMBER);
	void	~FileList();
	
public:
	void	SetFileList(LPCSTR lpcstrListName,LPCSTR lpcstrSubPath, int nListSize = MAX_RECENT_FILE_NUMBER);
	bool 	Add(LPCSTR lpcstrItem);
	string 	Get(int nIndex = 0, bool bInitShowList = true);
	/// AW 03/09/06 ADD_RECENT_FILE_LIST_CLASS
	//string	GetDisplayName(int nIndex =0, bool bRemoveVerboseInfo = true);
	virtual	string	GetDisplayName(int nIndex =0, bool bRemoveVerboseInfo = true)
	{
		string strFileName = Get(nIndex);
		return GetFileName(strFileName, false);
	}
	/// END ADD_RECENT_FILE_LIST_CLASS
	void	SetMaxSize(int nSetSizeSize = 0); ///nSetSizeSize = 0 mean not reset size, just clear
	int		GetSize();
	bool	ReloadList();
	bool	SaveList();
	
private:
	string	getSelectRow(int nIndex, bool bUpdateSelectRowToHeader);
	void	setList(int nListSize);
	bool 	loadListFromIni();
	bool 	saveListToIni();

private:
	string			m_strListName;
protected: /// AW 03/09/06 ADD_RECENT_FILE_LIST_CLASS
	string			m_strSubPath;
	int			  	m_nListSize;
	vector<string>	m_vsFileList;
};

void FileList::FileList( )
{
	SetFileList("", "",0);
}

void FileList::FileList(LPCSTR lpcstrListName,LPCSTR lpcstrSubPath,  int nListSize )
{
	SetFileList(lpcstrListName,lpcstrSubPath, nListSize);
}

void FileList::~FileList()
{
//	saveListToIni();
}


void	FileList::SetFileList(LPCSTR lpcstrListName, LPCSTR lpcstrSubPath, int nListSize )
{
	m_strListName = lpcstrListName;
	m_strSubPath  = lpcstrSubPath;
	
	setList(nListSize);
	m_vsFileList.RemoveAll();
	loadListFromIni();

}
bool FileList::Add(LPCSTR lpcstrItem)
{
	if(lpcstrItem == NULL)
		return false;
	
	int nDuplicateAddIndex = m_vsFileList.Find(lpcstrItem);
	
	if( nDuplicateAddIndex>=0)
		m_vsFileList.RemoveAt(nDuplicateAddIndex);
	
	//if( m_vsFileList.Find(lpcstrItem) >=0)
		//return true;
	
	m_vsFileList.InsertAt(0, lpcstrItem);
	
	if(GetSize() > m_nListSize)
		m_vsFileList.SetSize(m_nListSize);
	
	return true;
}

string FileList::Get(int nIndex, bool bInitShowList)
{
	if(nIndex >= GetSize() || nIndex < 0)
		return "";
	
	string strSeletedFile = getSelectRow(nIndex, bInitShowList);

	return strSeletedFile;
}

/// AW 03/09/06 ADD_RECENT_FILE_LIST_CLASS
/*
string	FileList::GetDisplayName(int nIndex , bool bRemoveVerboseInfo )
{
	string strFileName = Get(nIndex);
	
	string strDisplayName = okutil_composite_name_from_file_path(strFileName, m_strSubPath);
	
	//string strUserPrefix = "User:";
	
	///DSC 8/4/05 KEEP_FULL_COMPOSITE_NAME
	/*if(bRemoveVerboseInfo)
	{
		///Remove verbose information.
		int nStartRemove, nEndRemove;
		nStartRemove = strDisplayName.Find("(");
		nEndRemove   = strDisplayName.Find(")");
		//if(strDisplayName.Find(strUserPrefix) == 0)
			//nStartRemove = 0;
		strDisplayName.Delete(nStartRemove, nEndRemove - nStartRemove +1);
		
		strDisplayName.TrimLeft();
	}
	*/
	///end KEEP_FULL_COMPOSITE_NAME
/*	
	return strDisplayName;
}
*/
/// END ADD_RECENT_FILE_LIST_CLASS


void	FileList::SetMaxSize(int nSetSizeSize)
{
	setList(nSetSizeSize);
}

int		FileList::GetSize()
{
	return m_vsFileList.GetSize();
}

void	FileList::setList(int nSetListSize)
{
	m_nListSize = nSetListSize;
	
	if(GetSize() > nSetListSize)
		m_vsFileList.SetSize(nSetListSize);		
}

bool	FileList::ReloadList()
{
	return loadListFromIni();
}

bool	FileList::SaveList()
{
	return saveListToIni();
}

string	 FileList::getSelectRow(int nIndex, bool bUpdateSelectRowToHeader)
{
	string strSeletedFile = m_vsFileList[nIndex];
	
	if(!bUpdateSelectRowToHeader)
	{
		m_vsFileList.RemoveAt(nIndex);
		Add(strSeletedFile);
	}
	
	return strSeletedFile;		
}

bool	FileList::loadListFromIni()
{
	
	INIFile	iniFile(STRING_LIST_SETTING_FILE);
	vector<string> vsKeyNames;
	iniFile.GetKeyNames(vsKeyNames, m_strListName );
	string strValue;
	
	for(int ii=0; ii<vsKeyNames.GetSize(); ii++)
	{
		strValue = iniFile.ReadString(m_strListName, vsKeyNames[ii]);
		if(strValue.IsFile())
			m_vsFileList.Add(strValue);		
	}
		
	return true;
}

bool	FileList::saveListToIni()
{
	if(m_nListSize <= 0 || GetSize() <= 0 || m_strListName.IsEmpty())
		return false;

	INIFile	iniFile(STRING_LIST_SETTING_FILE);
	string strKeyName;
	
	///1. Remove Old list.
	if(!update_ini_line(iniFile,m_strListName, NULL, NULL ))
		return false;
	
	///2: Update new list
	for(int n=0; n < GetSize(); n++)
	{
		strKeyName = FILE_LIST_PREFIX + n;
		update_ini_line(iniFile,m_strListName, strKeyName, m_vsFileList[n] );
	}
	return true;
}

/// AW 03/09/06 ADD_RECENT_FILE_LIST_CLASS

/**
	please see the codes in XFDialog and QueryBldDlg
	1) Need derive class from MRFlist and provide your own GetDisplayName method if need, and add data member m_MRFList;
	2) Call initMRFList method in OnInitDialog.
	3) Write your own OnSelMostRecentFileList method in your DLG class
	4) In OnDestroy of dlg, call SaveList()

*/
class MRFList: public FileList
{

public:
	MRFList() 
	{
	}
	
	MRFList(const string& strIniSectionName, const string& strFolderName, int nListSize = MAX_RECENT_FILE_NUMBER)
	: FileList(strIniSectionName, strFolderName, nListSize)
	{
	}
	///Sophy 10/23/2010 ORG-1179 REMOVE_SEPARATOR_AND_JUNK_MENUITEM
	BOOL		RemoveMenuItem(int nItemID)
	{
		m_Menu.RemoveMenu(nItemID, MF_BYCOMMAND);
		return TRUE;
	}
	///end REMOVE_SEPARATOR_AND_JUNK_MENUITEM
private:
	Menu 		m_Menu;
	int			m_nMRBeginID, m_nMRSperatorID, m_nIDCLastSubMenuID;	

public:
///------------ CPY AW 03/15/06 ADD_RECENT_FILE_LIST_CLASS
	///Jasmine 04/11/06, set BeginSubMenuID and SeparatorID as one's require
	bool Init(HWND hWnd, int nIDCLastSubMenuID, LPCSTR lpcszIniSectionName, LPCSTR lpcszFolderName = NULL, 
	int nIDCBeginSubMenuID = IDC_RECENT_FILE_LIST_BEGIN, int nIDCSeparatorID = IDC_XFM_SEPARATOR,
	//---- CPY 4/28/06 MRF_ON_POPUP_MENU
	int nMenuPos = 0, int nPopupPos = -1)
	//----
	{
		//HWND 	hWnd = GetSafeHwnd();
		HMENU 	hMenu = GetMenu(hWnd);
		if ( hMenu )
		{
			//---- CPY 4/28/06 MRF_ON_POPUP_MENU
			if(nMenuPos >= 0)
			{
				HMENU hSubMenu = GetSubMenu(hMenu, nMenuPos);
				if(NULL == hSubMenu)
					out_int("error in menu position=", nMenuPos);
				if(hSubMenu && nPopupPos >= 0)
				{
					hSubMenu = GetSubMenu(hSubMenu, nPopupPos);
					if(NULL == hSubMenu)
						out_int("error in popup position=", nPopupPos);
				}
				if(hSubMenu)
					hMenu = hSubMenu;
				else
					return false;
			}
			//---- end MRF_ON_POPUP_MENU
			SetFileList(lpcszIniSectionName, lpcszFolderName);
			
			m_nMRBeginID = nIDCBeginSubMenuID;
			m_nMRSperatorID = nIDCSeparatorID;
			m_nIDCLastSubMenuID = nIDCLastSubMenuID;
			
			Menu myMenu(hMenu);
			initMenu(myMenu);
			return true;
		}
		return false;
	}
private:
///---------------- END ADD_RECENT_FILE_LIST_CLASS
	void initMenu(const Menu& Mymenu)
	{
		m_Menu = Mymenu;	
		initRecentFileListMenu(true);
	}
public:
	bool 	AddUpdateRecentFileList(LPCSTR lpcszFilePath)
	{
		Add(lpcszFilePath);
		updateRecentFileListMenu(true);//should add Separator
		
		return true;
	}
	string GetFromID(int nID, bool bInitShowList = true )
	{
		int nRecentlyFileIndex =  nID - m_nMRBeginID;
		return Get(nRecentlyFileIndex, bInitShowList);
	}



private:
	bool   initRecentFileListMenu(bool bSeparator)
	{
		insertFileList(bSeparator);
		return true;
	
	}

	bool    insertFileList(bool bSeparator)
	{
		
		int 	nNewID = m_nMRBeginID;
		int nListSize = GetSize();
		if ( nListSize <= 0) 
			return true;
		if(bSeparator)
			m_Menu.InsertMenu(m_nIDCLastSubMenuID, MF_SEPARATOR, m_nMRSperatorID);
		
		for( int index=0; index<nListSize; index++)
		{
			m_Menu.InsertMenu(m_nMRSperatorID, MF_STRING, nNewID++, GetDisplayName(index));
		}
		return true;
	}
	bool    removeAllFileList(bool bSeparator)
	{
	
		if(bSeparator)
			m_Menu.RemoveMenu(m_nMRSperatorID, MF_SEPARATOR);
		int nListSize = GetSize();
		for(int index=0; index<nListSize; index++)
		{
			m_Menu.RemoveMenu(m_nMRBeginID + index, MF_STRING);
		}
		return true;
	
	}
	bool   updateRecentFileListMenu(bool bSeparator)
	{	
		removeAllFileList(bSeparator);	
		insertFileList(bSeparator);	
		
		return true;
		
	}

};

#endif //_FILE_LIST_H
/// END ADD_RECENT_FILE_LIST_CLASS
