#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	fld_folder,
	fld_recursive,
	fld_open,
	fld_project,
};
enum{
	match_none,
	match_wkblong,
	match_wkbshort,
	match_comments,
};
enum{
	rename_lname,
	rename_sname,
	rename_wksname,
	rename_reset,
};
//put additional include files here

//put your own support static functions here
enum{
	folder_active = 0,
	folder_active_recursive,
	folder_active_open,
	folder_project,
};

enum{
	key_none = 0,
	key_lname,
	key_sname,
	key_comments,
};

enum{
	rename_wkb_lname = 0,
	rename_wkb_sname,
	rename_wks_sname,
	rename_none,
};

static bool s_bNew = false; // keep if the WorksheetPage is generate by XF <new>

// output Workbook is exclude
static int _get_page_names_in_folder(vector<string>& vsPageNames, int nFoldOption, LPCSTR lpszExcludePage)
{
	Folder fld = Project.ActiveFolder();
	bool bRecursive = false;
	int nPageShowState = -1;
	switch ( nFoldOption )
	{
	case folder_active:
		break;
	
	case folder_active_open:
		nPageShowState = PAGE_OPEN;
		
		break;
	case folder_project:
		fld = Project.RootFolder;	
	case folder_active_recursive:	
		bRecursive = true;
				
		break;
	default:
		return 0;
	}
	
	get_folder_pages_name( fld, vsPageNames, EXIST_WKS, bRecursive, nPageShowState ); 
	
	int nPos = vsPageNames.Find(lpszExcludePage);
	
	if ( -1 != nPos )
		vsPageNames.RemoveAt(nPos);
	
	return vsPageNames.GetSize();
}


static int _copy_matched_book(Page& pgDst, const Page& pgSrc, int nRename)
{
	int nOldNumLayer = pgDst.Layers.Count();
		
	if ( pgDst.AddLayers(pgSrc) )
	{
		int nAddLayerNum = pgDst.Layers.Count() - nOldNumLayer;
		
		for (int ii=0; ii < nAddLayerNum; ii++)
		{			
			bool bNeedRename = true;
			string strNewName;
			switch ( nRename )
			{
			case rename_wkb_lname:
				strNewName = pgSrc.GetLongName();
				
				break;
			case rename_wkb_sname:
				strNewName = pgSrc.GetName();
				
				break;
			case rename_wks_sname:
				strNewName = pgSrc.Layers(ii).GetName();
				
				break;
			case rename_none:
			default:
				bNeedRename = false;
				break;
			}
			
			if ( bNeedRename  && !strNewName.IsEmpty() )
			{
				pgDst.Layers(nOldNumLayer + ii).SetName(strNewName, OCD_ENUM_NEXT);
			}
		}
		
		return nAddLayerNum;
	}
	
	return 0;
}

static int _combine_books_with_options(WorksheetPage& owp, vector<string>& vsPageNames, bool bKeepSrcPage, int nRename, bool bSingleSheet, int nMatch, LPCSTR lpszKey)
{
	int nCopyBookNum = 0;
	int nCopySheetNum = 0;
	
	for ( int ii=0; ii < vsPageNames.GetSize(); ii++ )
	{
		Page pg(vsPageNames[ii]);
		// single workbook check, need take care if empty workbook
		if ( bSingleSheet && pg.Layers.Count() != 1 )
		{
			//vsPageNames.RemoveAt(ii--);
			continue;
		}
		// march string check
		bool bNeedMarch = false;
		string strVal;
		switch (nMatch)
		{
		case key_none:
			
			break;
		case key_lname:
			bNeedMarch = true;
			strVal = pg.GetLongName();
			
			break;
		case key_sname:
			bNeedMarch = true;
			strVal = pg.GetName();
			
			break;
		case key_comments:
			bNeedMarch = true;
			strVal = pg.GetComments();
			
			break;
		default:
			break;
		}
		
		//if ( bNeedMarch && 0 != strVal.CompareNoCase(lpszKey) )
		if ( bNeedMarch && !strVal.Match(lpszKey) )
		{
			//vsPageNames.RemoveAt(ii--);
			continue;
		}
		
		// copy workbook
		nCopySheetNum += _copy_matched_book(owp, pg, nRename);
		nCopyBookNum++;
		
		if ( !bKeepSrcPage )
			pg.Destroy();
	}
	
	return nCopySheetNum;
}


void merge_book(const int& fld, const int& keep, const int& single, const int& match, const string& key, const int& rename, WorksheetPage& owp)
{
	if ( !owp )
		XF_THROW(CER_INVALID_ARGUMENT); // _L("Invalid workbook")
	
	vector<string> vsPageNames;
	_get_page_names_in_folder(vsPageNames, fld, owp.GetName());
	
	if ( s_bNew )
	{
		owp.Layers().Destroy(OCD_DEL_LINKED_OBJS); // destroy layer generate by <new>
	}
	
	int nCopySheetNum = _combine_books_with_options(owp, vsPageNames, keep, rename, single, match, key);
	
	if ( 0 == nCopySheetNum )
	{
		owp.Destroy();
		XF_THROW(CER_INVALID_ARGUMENT); // _L("No workbook merged")
	}
}

//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int merge_book_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return merge_book_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	if ( 0 == lstrcmp(lpcszNodeName, "match") )
	{
		if ( key_none == trGetN.match.nVal )
			trGetN.key.Enable = 0;
		else
			trGetN.key.Enable = 1;
	}
	
	return false;

}

int merge_book_make_tree(TreeNode& tr, LPCSTR lpcszVarName)
{
	return false;
}
//nGetNDialog = 0,1,2, corresponding to the XF GetN dropdown, 0 = dialog is not used
//you can change nRet to be one of XFEVT_PROCEED (defualt), XFEVT_ABORT, XFEVT_PROCEED_NO_DLG or XFEVT_PROCEED_WITH_DLG(when nGetNDialog = 0)
//nGetNDialog = -1 when Ok on GetN dialog to allow handler to preocess <auto> etc variables
//dwCntrl is combination of bits
//LTXF_FROM_GUI_MENU, LTXF_FROM_GUI_PROMPT, LTXF_FROM_AUTO_UPDATE, LTXF_FROM_FUNCTION, LTXF_THEME_USED, LTXF_CHANGE_PARAM
void merge_book_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	if(PDS_NEW == okutil_cvt_str_to_predefined_type(trGetN.owp.strVal))
	{
		s_bNew = true;
	}
	
	if ( nGetNDialog > 0 ) // dialog open
	{
		if ( key_none == trGetN.match.nVal )
			trGetN.key.Enable = 0;
		else
			trGetN.key.Enable = 1;
	}
}
//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int merge_book_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
