/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/* ***************************************************** */
/********************************************************************/
// MultiActions.cpp: implements the CMultiActions class.
// It defines the following operations:
//		void Do();
//			--Notify the undo manager,
//			--Perform do operation of all the member actions.
//
//		void Undo();
//			--perform undo operation of all the member actions.
//
//		void Redo();
//			--perform redo operation of all the member actions.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "fugenDoc.h"
#include "Undo/MultiActions.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

CMultiActions::CMultiActions(fugenDoc* aTarget)
:CDocAction(aTarget){
}

CMultiActions::CMultiActions(fugenDoc* aTarget, CDocAction* action)
:CDocAction(aTarget), m_actions(1, action){
	action->SetAutoNotify(false);
}

//Copy constructor.
CMultiActions::CMultiActions(CMultiActions& other)
:CDocAction(other){
	m_actions.swap(other.m_actions);
}

CMultiActions::~CMultiActions(){
	erase(begin(), end());
}

//Assignment
CMultiActions& CMultiActions::operator=(CMultiActions& other){
	CMultiActions tmp(other);
	m_actions.swap(tmp.m_actions);
	return *this;
}

void CMultiActions::Do(){
	CDocAction::Do();

	fugenDoc& doc=*(actionTarget());
	doc.lockAllWindowsUpdate();
	iterator i=begin(), ie=end();
	for(; i!=ie; i++)
		(*i)->Do();
	doc.unlockAllWindowsUpdate();
	doc.InvalidateAllStdViews();
}

void CMultiActions::Undo(){
	CDocAction::Undo();
	fugenDoc& doc=*(actionTarget());

	doc.lockAllWindowsUpdate();
	reverse_iterator i=rbegin(), ie=rend();
	for(; i!=ie; i++)
		if(*i)
			(*i)->Undo();
	doc.unlockAllWindowsUpdate();
	doc.InvalidateAllStdViews();
}

void CMultiActions::Redo(){
	CDocAction::Redo();
	fugenDoc& doc=*(actionTarget());
	doc.lockAllWindowsUpdate();
	iterator i=begin(), ie=end();
	for(; i!=ie; i++)
		(*i)->Redo();
	doc.unlockAllWindowsUpdate();
	doc.InvalidateAllStdViews();
}

//////////Member Function//////////

CMultiActions::iterator CMultiActions::erase(
	iterator first, iterator last
){
	for(; first != last; ++first)
		delete *first;
	return m_actions.erase(first, last);
}

// pop last element.
void CMultiActions::pop_back(){
	delete back();
	m_actions.pop_back();
}

// push element x at the end.
void CMultiActions::push_back(CDocAction* x){
	x->SetAutoNotify(false);
	if(!actionTarget())
		set_target(x->actionTarget());
	m_actions.push_back(x);
}

//push elements in gelps at the end.
//The ownership of CDocAction* of actions are transfered to this CMultiActions.
//void CMultiActions::push_back(std::vector<CDocAction*>& actions){
//	m_actions.insert(end(), actions.begin(), actions.end());
//}

//Resize the gelp.
void CMultiActions::resize(size_type n){
	size_t nold=size();
	if(n==nold) return;
	if(n>nold){
		m_actions.resize(n,0);
	}else{
		for(size_t i=n; i<nold; i++) delete m_actions[i];
		m_actions.resize(n);
	}
}

//Set stack kind.
void CMultiActions::set_as_undo_stack(){
	iterator i=begin(), ie=end();
	for(; i!=ie; i++) (*i)->set_as_undo_stack();
	CDocAction::set_as_undo_stack();
}
void CMultiActions::set_as_redo_stack(){
	iterator i=begin(), ie=end();
	for(; i!=ie; i++) (*i)->set_as_redo_stack();
	CDocAction::set_as_redo_stack();
}
