/*------------------------------------------------------------------------------*
 * File Name: SelectCategoryDlg.cpp												*
 * Creation: Kenny 11/10/2009													*
 * Purpose: OriginC Source file													*
 * Copyright (c) OriginLab Corp. 2009											*
 * All Rights Reserved															*
 *																				*
 * Modification Log:															*
 *	Folger 07/13/10 ORG-543 PROMPT_USER_FOR_WHETHER_COPY_FDF_TO_UFF_WHEN_ADD_IN_FO
 *	Folger 10/21/2010 ORG-1310-P1 DRAG_AND_GROP_FDF_INTO_ORIGIN_FAILED_IF_FITFUNC_FOLDER_NOT_EXIST_IN_UFF
 *------------------------------------------------------------------------------*/

#include <Origin.h>
#include <../OriginLab/DialogEx.h>
#include "nlsf_utils.h"
#include <FDFTree.h>

#include "FunctionGroup.h"
#include "NumFunctionOrganizer.h"

#define STR_DLG_NAME 			_L("Select Category Dlg")
#define STR_DEF_CATE			"Origin Basic Functions"

class CSelectCategoryDlg : public ResizeDialog
{	
public:
	CSelectCategoryDlg(vector<string>& vsFiles);
	~CSelectCategoryDlg();

public:
	int DoModalEx(HWND hWndParent = NULL, DWORD dwOptions = 0, LPCSTR OpsName = NULL);

protected:
	void InitCategoryList();
	bool PromptToRename(LPCSTR lpcszMsg, string& strName);
	bool CheckGetCategoryName(string& strCategory);
	bool CheckGetFunctionName(int nIndex, string& strFuncName, string& strFDFPath, bool& bCopyToDefDir);
	///------ Folger 10/21/2010 ORG-1310-P1 DRAG_AND_GROP_FDF_INTO_ORIGIN_FAILED_IF_FITFUNC_FOLDER_NOT_EXIST_IN_UFF
	BOOL CheckCreateFDFFolderInUFF();
	///------ End DRAG_AND_GROP_FDF_INTO_ORIGIN_FAILED_IF_FITFUNC_FOLDER_NOT_EXIST_IN_UFF

EVENTS_BEGIN
	ON_INIT(OnInitDialog) 
	ON_READY(OnReady)
	ON_SIZE(OnDlgResize)
	ON_DESTROY(OnDestroy)
	ON_HELPINFO(OnHelp)
	ON_CANCEL(OnClose)
	ON_OK(OnOK)
	ON_LBN_SELCHANGE(IDC_CATLIST, OnSelCategoryList)
	ON_EN_CHANGE(IDC_CATEDIT, OnEditChangeCategory)
EVENTS_END

	BOOL OnInitDialog();
	BOOL OnReady();
	BOOL OnDlgResize(int nType, int cx, int cy);
	BOOL OnDestroy();
	BOOL OnHelp(int &nHelpID, int nIdCtrlFocus);
	BOOL OnClose();
	BOOL OnOK();

	BOOL OnSelCategoryList(Control ctrl);
	BOOL OnEditChangeCategory(Control ctrl);
private:
	void updateButtonStatus();
	bool isEnterBuiltinCategory();
private:
	ListBox			m_CatListBox;
	Edit			m_edCatName;
	int				m_nCurSelCatIndex;
	vector<string>	m_vsCategories;
	vector<int>		m_vnSeparatorIndices;
	vector<string>	m_vsFDF;
	Tree			m_trCategoryFunction;
};

/*----------------------------------------------------------------------------*/
/* Constructors/Destructors of CSelectCategoryDlg
/*----------------------------------------------------------------------------*/

CSelectCategoryDlg::CSelectCategoryDlg(vector<string>& vsFiles)
	: ResizeDialog(IDD_SELECT_CAT, "ODlg8")
{
	m_nCurSelCatIndex = -1;
	m_vsFDF = vsFiles;
}

CSelectCategoryDlg::~CSelectCategoryDlg()
{
	
}

/*----------------------------------------------------------------------------*/
/* Event handlers of CSelectCategoryDlg
/*----------------------------------------------------------------------------*/

BOOL CSelectCategoryDlg::OnInitDialog()
{
	ResizeDialog::OnInitDialog(0, STR_DLG_NAME);

	m_CatListBox = GetDlgItem(IDC_CATLIST);
	m_edCatName = GetDlgItem(IDC_CATEDIT);

	InitCategoryList();
	updateButtonStatus();

	return TRUE;
}

BOOL CSelectCategoryDlg::OnReady()
{
	SetInitReady();
	return TRUE;
}

BOOL CSelectCategoryDlg::OnDlgResize(int nType, int cx, int cy)
{
	if(!IsInitReady())
		return FALSE;
	return TRUE;
}

BOOL CSelectCategoryDlg::OnDestroy()
{
	ResizeDialog::OnDestroy();
	return TRUE;
}

BOOL CSelectCategoryDlg::OnHelp(int &nHelpID, int nIdCtrlFocus)
{
	return TRUE;
}

BOOL CSelectCategoryDlg::OnClose()
{
	return TRUE;
}

///------ Folger 10/21/2010 ORG-1310-P1 DRAG_AND_GROP_FDF_INTO_ORIGIN_FAILED_IF_FITFUNC_FOLDER_NOT_EXIST_IN_UFF
BOOL CSelectCategoryDlg::CheckCreateFDFFolderInUFF()
{
	NLFunctionList	fo;
	return CheckMakePath(fo.GetFunctionFolder(USER_FOLDER));
}
///------ End DRAG_AND_GROP_FDF_INTO_ORIGIN_FAILED_IF_FITFUNC_FOLDER_NOT_EXIST_IN_UFF

BOOL CSelectCategoryDlg::OnOK()
{
	string strCategory = m_edCatName.Text;
	if ( !CheckGetCategoryName(strCategory) )
	{
		return FALSE;
	}
	bool bOK			= true;
	bool bIsBuiltInCate	= isEnterBuiltinCategory();
	int nUpdatedFile	= 0;
	if ( !bIsBuiltInCate )
	{
		bOK = nlsf_update_category(strCategory, NULL);
	}
	if ( bOK )
	{
		///------ Folger 07/13/10 ORG-543 PROMPT_USER_FOR_WHETHER_COPY_FDF_TO_UFF_WHEN_ADD_IN_FO
		//int nMsgRet = MessageBox(GetSafeHwnd(), STR_MSG_COPY_FILE, STR_MSG_CAPTION, MB_YESNOCANCEL);
		//if ( IDCANCEL == nMsgRet )
			//return TRUE;
		int nMsgRet = MessageBox(GetSafeHwnd(), STR_MSG_COPY_FILE, STR_MSG_CAPTION, MB_YESNO);
		///------ End PROMPT_USER_FOR_WHETHER_COPY_FDF_TO_UFF_WHEN_ADD_IN_FO

		bool bCopyToDefDir = IDYES == nMsgRet;
		///------ Folger 10/21/2010 ORG-1310-P1 DRAG_AND_GROP_FDF_INTO_ORIGIN_FAILED_IF_FITFUNC_FOLDER_NOT_EXIST_IN_UFF
		if ( bCopyToDefDir )
		{
			CheckCreateFDFFolderInUFF();
		}
		///------ End DRAG_AND_GROP_FDF_INTO_ORIGIN_FAILED_IF_FITFUNC_FOLDER_NOT_EXIST_IN_UFF

		NLFunctionList fo;
		for (int ii = 0; ii < m_vsFDF.GetSize(); ++ii)
		{
			string strOriginFuncName;
			Tree trInfo;
			nlsf_FDF_to_tree(m_vsFDF[ii], &trInfo);
			if ( trInfo.GeneralInformation.FunctionName )
				strOriginFuncName = trInfo.GeneralInformation.FunctionName.strVal;

			string strFuncName		= strOriginFuncName;
			string strFDFPath		= m_vsFDF[ii];

			bool bUpdateFunction	= true;
			bool bIsValidFunc		= true;
			bool bCopyCurToDefDir	= bCopyToDefDir;

			if ( !CheckGetFunctionName(ii, strFuncName, strFDFPath, bCopyCurToDefDir) )
			{
				continue;
			}

			if ( bUpdateFunction )
			{
				BOOL bContinue = TRUE;
				if ( bCopyCurToDefDir )
				{
					ASSERT( strFDFPath.CompareNoCase(m_vsFDF[ii]) != 0 );
					bContinue = CopyFile(m_vsFDF[ii], strFDFPath);
				}
				if ( strOriginFuncName.CompareNoCase(strFuncName) != 0 )
				{
					// need to update the function name field of the fdf file.
					if ( trInfo.GeneralInformation.FunctionName )
						trInfo.GeneralInformation.FunctionName.strVal = strFuncName;
					string strFileName;
					DeleteFile(strFDFPath);
					bContinue = nlsf_tree_to_FDF(strFDFPath, &trInfo, &strFileName);
				}
				if ( bContinue )
				{
					bOK = nlsf_update_function(strCategory, strFuncName, NULL, strFDFPath, 
							bCopyCurToDefDir ? ORIGIN_PATH_USER : UNDEF_FOLDER);
					if ( bOK )
						++nUpdatedFile;
				}
			}
		}
	}
	return TRUE;
}

BOOL CSelectCategoryDlg::OnSelCategoryList(Control ctrl)
{
	int nCurSel = m_CatListBox.GetCurSel();
	vector<uint> vIndex;
	int nFindRet = m_vnSeparatorIndices.Find( MATREPL_TEST_EQUAL, nCurSel, vIndex );
	if ( nFindRet <= 0 )
	{
		string strCategory;
		m_CatListBox.GetText( nCurSel, strCategory);
		m_edCatName.Text = strCategory;
		m_nCurSelCatIndex = nCurSel;
	}
	else
	{
		m_CatListBox.SetCurSel(m_nCurSelCatIndex);
	}
	updateButtonStatus();
	return TRUE;
}

BOOL CSelectCategoryDlg::OnEditChangeCategory(Control ctrl)
{
	updateButtonStatus();
	return TRUE;
}

/*----------------------------------------------------------------------------*/
/* Member functions of CSelectCategoryDlg
/*----------------------------------------------------------------------------*/

int CSelectCategoryDlg::DoModalEx(HWND hWndParent /*= NULL*/, DWORD dwOptions /*= 0*/, LPCSTR OpsName /*= NULL*/)
{
	InitMsgMap();
	return DoModal(hWndParent, dwOptions, OpsName);
}

void CSelectCategoryDlg::InitCategoryList()
{
	NLFunctionList fo;
	int nSize = fo.GetCategoryList(m_trCategoryFunction);
	fo.GetCategoryList(m_vsCategories, m_vnSeparatorIndices);

	for (int jj = 0; jj < m_vsCategories.GetSize(); ++jj)
	{
		m_CatListBox.AddString( m_vsCategories[jj] );
	}

	if ( m_vsCategories.GetSize() > 0 )
	{
		m_nCurSelCatIndex = 0;
		m_CatListBox.SetCurSel(m_nCurSelCatIndex);
		m_edCatName.Text = m_vsCategories[0];
	}
}

bool CSelectCategoryDlg::CheckGetCategoryName(string& strCategory)
{
	NLFunctionList fo;
	bool bIsValidCate = true;
	do 
	{
		string strErrMsg;
		string strAutoCorrectCateName = strCategory;
		Tree trJunk;
		bIsValidCate = fo.CheckCateName(strAutoCorrectCateName, trJunk, &strErrMsg);

		if ( !bIsValidCate )
		{
			string strDetailErrMsg;
			strDetailErrMsg.Format( _L("You need to rename the category \"%s\" due to this reason:\n\n%s"), strCategory, strErrMsg );

			MessageBox(GetSafeHwnd(), strDetailErrMsg, STR_MSG_CAPTION, MB_OK);
			return false;
		}
	} while ( !bIsValidCate );
	return true;
}

bool CSelectCategoryDlg::CheckGetFunctionName(int nIndex, string& strFuncName, string& strFDFPath, bool& bCopyToDefDir)
{
	NLFunctionList fo;
	bool bIsValidFunc	= true;
	bool bOK			= true;
	TreeNode trCategory	= m_trCategoryFunction.FirstNode;
	do 
	{
		string strErrMsg;
		string strAutoCorrectFuncName = strFuncName;
		bIsValidFunc = fo.CheckFuncName(strAutoCorrectFuncName, trCategory, &strErrMsg, NULL, false, 
			FO_NAME_CHECKING_RETURN_ON_INVALID);

		// Avoid replacing existing file
		if ( bIsValidFunc && bCopyToDefDir )
		{
			string strDstUFFPath = fo.GetFunctionFolder(USER_FOLDER) + strFuncName + STR_FDF_FILE_EXT;
			bCopyToDefDir = strDstUFFPath.CompareNoCase(m_vsFDF[nIndex]) != 0;
			if( bCopyToDefDir && strDstUFFPath.IsFile() )
			{
				int nMsgRet = MessageBox(GetSafeHwnd(), 
						"Would you like to replace the existing file\n" + strDstUFFPath + " ?\nSelect 'No' to use file from the current location.", 
						STR_MSG_CAPTION, MB_YESNOCANCEL | MB_ICONEXCLAMATION);
				if( IDCANCEL == nMsgRet )
				{
					bOK = false;
					break;
				}
				if ( IDNO == nMsgRet )
				{
					bCopyToDefDir = false;
					break;
				}
			}
			strFDFPath = strDstUFFPath;
		}
		if ( !bIsValidFunc )
		{
			string strDetailErrMsg;
			strDetailErrMsg.Format( _L("You need to rename the function \"%s\" in \n\"%s\"\n due to this reason:\n\n%s"), 
				strFuncName, m_vsFDF[nIndex], strErrMsg );
			bOK = PromptToRename(strDetailErrMsg, strFuncName);
		}
	} while ( bOK && !bIsValidFunc );
	return bOK;
}

bool CSelectCategoryDlg::PromptToRename( LPCSTR lpcszMsg, string& strName )
{
	GETN_TREE(trRename)
	GETN_MULTILINE_TEXT(Warn, lpcszMsg, "")	GETN_HINT
	GETN_EDIT_DISPLAY_WIDTH_RANGE("50-1000")
	GETN_STR(Name, _L("New Name"), strName)
	if( !GetNBox(trRename, _L("Rename"), NULL, NULL, NULL, GetSafeHwnd()) )
		return false;
	strName = trRename.Name.strVal;
	return true;
}

void CSelectCategoryDlg::updateButtonStatus()
{
	const string strCategory = m_edCatName.Text;
	BOOL bEnable = !strCategory.IsEmpty();
	GetDlgItem(IDOK).Enable = bEnable;
}

bool CSelectCategoryDlg::isEnterBuiltinCategory()
{
	string strCategory;
	m_CatListBox.GetText( m_CatListBox.GetCurSel(), strCategory);
	return m_edCatName.Text.Compare(strCategory) == 0;
}

/*----------------------------------------------------------------------------*/
/* Public interface of CSelectCategoryDlg
/*----------------------------------------------------------------------------*/

BOOL SelectCategoryDlg(StringArray& vsDragNDropFileNames, string &strWinName, int iWinLayer)
{
	CSelectCategoryDlg dlg(vsDragNDropFileNames);
	if ( IDOK == dlg.DoModalEx( GetWindow() ) )
	{
		;
	}
	return 0;
}