// UndoManager.cpp: implementation of the UndoManager class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ImageGrinder.h"
#include "ImageGrinderDoc.h"
#include "UndoManager.h"
#include <Compost\FeatureGrid.hpp>

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  Undo Command

void UndoCommand::Attach(UndoCommand *cmd)
{
if(Next) 
	Next->Attach(cmd);
else
	Next=cmd;
}

void UndoCommand::ExecuteUndo(UndoCommand **revcom)
{
if(Next) Next->ExecuteUndo(revcom);
}
/*
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Rename
void RenameCommand::ExecuteUndo(UndoCommand **revcom)
{
	UndoCommand::ExecuteUndo(revcom);
	UndoCommand *com=new RenameCommand(Object);
	Object->SetName(OldName);	
	if(*revcom==NULL) *revcom=com; else (*revcom)->Attach(com);
}
*/
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Move
void MoveCommand::ExecuteUndo(UndoCommand **revcom)
{
	UndoCommand::ExecuteUndo(revcom);
	
	UndoCommand *com=new MoveCommand(Object,Parent);
	Parent->SetDrawFlags(Object);
	Object->feature_x_pos=xpos;
	Object->feature_z_pos=zpos;
	Parent->SetDrawFlags(Object);
	if(*revcom==NULL) *revcom=com; else (*revcom)->Attach(com);
}



// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> AddCommand
void AddCommand::ExecuteUndo(UndoCommand **revcom)
{
	UndoCommand::ExecuteUndo(revcom);
	UndoCommand *com=new DeleteCommand(Object,Parent);
	Parent->SetDrawFlags(Object);
	Parent->FGrid->Remove(Object);
	if(*revcom==NULL) *revcom=com; else (*revcom)->Attach(com);
}

// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DeleteCommand
void DeleteCommand::ExecuteUndo(UndoCommand **revcom)
{
	UndoCommand::ExecuteUndo(revcom);
	Compost::FeatureInstance *newfet;

	//!!! This corrupts the Stack;
	newfet=Parent->FGrid->Add(Fet,XPos,ZPos);
	Object=newfet;
	UndoCommand *com=new AddCommand(Object,Parent);
	if(*revcom==NULL) *revcom=com; else (*revcom)->Attach(com);
}
/*
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GroupCommand
void GroupCommand::ExecuteUndo(UndoCommand **revcom)
{
	UndoCommand::ExecuteUndo(revcom);
	UndoCommand *com=new GroupCommand(Object);
	Object->GetParent()->RemoveObject(Object);
	Parent->AddObject(Object);
	if(*revcom==NULL) *revcom=com; else (*revcom)->Attach(com);
}
*/
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  Command Stack

CommandStack::CommandStack()
{
	CommandCount=0;
	CommandMax=COMMAND_MAX;
}

void CommandStack::RemoveBottomCommand()
{
	Verify(CommandCount>=1);
	delete Commands[0];
	for(int i=1;i<CommandCount;i++) Commands[i-1]=Commands[i];
	CommandCount--;
}

void CommandStack::PushCommand(UndoCommand *cmd)
{
	Verify(cmd!=NULL);
	if(CommandCount>=(CommandMax-1)) 
		RemoveBottomCommand();
	Commands[CommandCount++]=cmd;
}

UndoCommand *CommandStack::Pop()
{
	if(CommandCount>0)
	{
		CommandCount--;
		return Commands[CommandCount];
	}

	return NULL;
}

UndoCommand *CommandStack::PopAndExecute()
{
	if(CommandCount>0)
	{
		CommandCount--;
		UndoCommand *revcom=NULL;
		Commands[CommandCount]->ExecuteUndo(&revcom);
		delete Commands[CommandCount];
		return revcom;
	}
	
	return NULL;
}

void CommandStack::Clear() 
{ 
while(CommandCount) 
	{
	UndoCommand *com=Pop();
	com->Discard();
	delete com;
	}
}

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Undo Manger 

UndoManager::~UndoManager()
{
}

void UndoManager::Undo()
{
RedoStack.PushCommand(UndoStack.PopAndExecute());
}

void UndoManager::Redo()	
{
UndoStack.PushCommand(RedoStack.PopAndExecute());
}

void UndoManager::AddCommand(UndoCommand *cmd)
{
RedoStack.Clear();
UndoStack.PushCommand(cmd);
}

