
#include "stdafx.h"
#ifdef ACTIVE_EDITOR

#include "itf/CpaMdf.hpp"
#include "itf/FRMBsMn.hpp"
#include "itf/FRMGest.hpp"

unsigned long CPA_Modif::LastSerial=0;


CPA_Modif::CPA_Modif(unsigned short pType, CString pName, BOOL pBlock /* = FALSE */)
{
	Type = pType;
	Name = pName;
	m_HasBeenDone = FALSE;
	if ( !pBlock ) LastSerial ++;
	Serial = LastSerial;
}
//-------------------------------------------------------------------


CPA_EditManager::CPA_EditManager(int iMaxUndo)
{
	NextPosition=NULL;
	PrevPosition=NULL;
	NextModif=NULL;
	PrevModif=NULL;
	CurrentIndex=0;
	m_iMaxUndo=iMaxUndo;

	m_bIsReDoing = FALSE;
	m_bIsUnDoing = FALSE;

}

CPA_EditManager::~CPA_EditManager(void)
{
	while(0<ListOfModifs.GetCount())
		delete ListOfModifs.RemoveTail();//I own the modif's, so I delete them

}

BOOL CPA_EditManager::AskFor(CPA_Modif * pModif, BOOL _bDeleteUponFailure /*= TRUE*/)
{
	// cannot insert a new modification while we are undoing or redoing another one
	if (m_bIsReDoing || m_bIsUnDoing)
		return FALSE;

	if(!pModif->Do()) 
	{
		if ( _bDeleteUponFailure )
			delete pModif;
		return FALSE;//if the modif don't succeed do not erase the list (redo are still available)
	}

	pModif->Done();
	while(CurrentIndex<ListOfModifs.GetCount())//no more Redo's
		delete ListOfModifs.RemoveTail();//I own the modif's, so I delete them
	if(m_iMaxUndo)
	{
		while(ListOfModifs.GetCount()>=m_iMaxUndo)
		{
			unsigned long CurrentSerial;
			POSITION pOldPosition;
			CPA_Modif *pOldModif;
			for
			(
				pOldModif=ListOfModifs.GetHeadElement(pOldPosition),CurrentSerial=pOldModif->GetSerial();
				pOldModif!=NULL && pOldModif->GetSerial()==CurrentSerial;
				pOldModif=ListOfModifs.GetNextElement(pOldPosition),
				CurrentIndex--
			)
			{
				delete pOldModif;
				ListOfModifs.RemoveAt(pOldPosition);
			}
		}
	}
	PrevPosition=ListOfModifs.AddTail(PrevModif=pModif);
	NextPosition=NULL;			//no more Redo's
	NextModif=NULL;				//no more Redo's
	CurrentIndex++;
	// Update dialog bar (for buttons)
	((FRMBaseMenu *) g_oFrameGest.ma_p_oWinArray[2][2])->fn_vInitGeneralDialogBarWithContext();
	return TRUE;
}

void CPA_EditManager::Reset(void)
{
	while(ListOfModifs.GetCount())//no more Modif's
		delete ListOfModifs.RemoveTail();
	NextPosition=NULL;
	PrevPosition=NULL;
	NextModif=NULL;
	PrevModif=NULL;
	CurrentIndex=0;
}

BOOL CPA_EditManager::Redo(void)
{
	BOOL OK,ret;
	unsigned long CurrentSerial;

	if (!CanRedo()) 
		return FALSE;

	m_bIsReDoing = TRUE;

	OK=TRUE;
	CurrentSerial=NextModif->GetSerial();

	for
	(
		;
		NextModif!=NULL && NextModif->GetSerial()==CurrentSerial;
		NextModif=ListOfModifs.GetNextElement(NextPosition),
		PrevModif=ListOfModifs.GetNextElement(PrevPosition),
		CurrentIndex++
	)
	{
		ret = NextModif->Do();
		if (ret) 
			NextModif->Done();
		OK = OK&&ret;
	}

	m_bIsReDoing = FALSE;
	return OK;
}

BOOL CPA_EditManager::Undo(void)
{
	BOOL OK,ret;
	unsigned long CurrentSerial;

	if (!CanUndo()) 
		return FALSE;

	m_bIsUnDoing = TRUE;

	OK=TRUE;
	CurrentSerial=PrevModif->GetSerial();

	for
	(
		;
		PrevModif!=NULL && PrevModif->GetSerial()==CurrentSerial;
		NextModif=ListOfModifs.GetPrevElement(NextPosition),
		PrevModif=ListOfModifs.GetPrevElement(PrevPosition),
		CurrentIndex--
	)
	{
		ret = PrevModif->Undo();
		if (ret) 
			PrevModif->Undone();
		OK = OK&&ret;
	}

	m_bIsUnDoing = FALSE;

	return OK;

}

CString CPA_EditManager::GetRedoName(void)
{
	if(!CanRedo()) return "No Redo Available";
	return "Redo "+NextModif->GetName();
}

CString CPA_EditManager::GetUndoName(void)
{
	if(!CanUndo()) return "No Undo Available";
	return "Undo "+PrevModif->GetName();
}

#endif // ACTIVE_EDITOR
