/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno             */
/* All rights reserved.                                             */
/* **************************************************************** */

// GLAUpdateAction.h: interface for the CGelAttribUpdateAction class.
// This class serves as MGAppearance update action
// It defines the following operations:
//
//		void Do();
//			--Notify the undo manager,
//			--Perform the operation.
//
//		void Undo();
//			-- delete the added attrib and add removed attrib.
//
//		void Redo();
//			-- delete the removed attrib and add added attrib.
//
//////////////////////////////////////////////////////////////////////

#if !defined(GLAUpdateAction_H)
#define GLAUpdateAction_H

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

class MGAppearance;
class MGAttribedGel;

#include "mg/Attrib.h"
#include "Undo/DocAction.h"


class CGelAttribUpdateAction : public CDocAction{
public:
	CGelAttribUpdateAction(fugenDoc *doc = 0);//Void ctor
	~CGelAttribUpdateAction()=default;
	CGelAttribUpdateAction(const CGelAttribUpdateAction& rhs)=delete;//Copy constructor.
	CGelAttribUpdateAction& operator=(const CGelAttribUpdateAction& rhs)=delete;//Copy assignment.
	CGelAttribUpdateAction(CGelAttribUpdateAction&& rhs)= default;//Move constructor.
	CGelAttribUpdateAction& operator=(CGelAttribUpdateAction&& rhs) = default;//Move assignment.

	///Add or replace action.
	///When objs already have the same type attribute as attrib,
	///this will replace the old MGGLAttrib, otherwise add attrib to MGAttribedGel.
	CGelAttribUpdateAction(
		fugenDoc *doc,
		const MGGelPositions& objs,///<MGAttribedGel that the following attrib will include.
		const MGGLAttrib& attrib///<adding attrib when gel does not have the same type MGGLAttrib,
		///<and replacing when gel have the same type.
	);
	CGelAttribUpdateAction(
		fugenDoc *doc,
		const MGGelPositions& objs,///<MGAttribedGel that the following attrib will include.
		UniqueGLAttribVec&& attribs///<adding attrib when gel does not have the same type MGGLAttrib,
		///<and replacing when gel have the same type.
		///<The ownership of attribs will be transfered to CGelAttribUpdateAction.
	);

	///Remove action. Remove the MGGLAttrib whose type is type_id.
	CGelAttribUpdateAction(
		fugenDoc *doc,
		const MGGelPositions& objs,///<MGAttribedGel that the following attrib will be removed from.
		MGGEL_TID type_id  ///<MGAttrib id that should be removed.
		);

	UniqueGLAttribVec& added_attrib();
	const UniqueGLAttribVec& added_attrib()const;
	MGGelPositions& agels();
	const MGGelPositions& agels()const;
	std::vector<UniqueGLAttribVec>& removed();
	const std::vector<UniqueGLAttribVec>& removed()const;
	long remove_type()const;

	virtual	void	Do();
	virtual	void	Undo();
	virtual	void	Redo();

	///Update the views. This will be invoked by CDocAction::update_all_views,
	///when DO, Undo, or Redo operations are invoked.
	void view_update(ACTION_TYPE at);

protected:

//the target is MGAttribedGel, the target is stored in m_agels.
	MGGelPositions m_agels;
	std::vector<UniqueGLAttribVec> m_removed;
		//m_agels[i] and m_removed[i] is a pair.
		//m_removed[i] is UniqueGLAttribVec that is removed from the target.
		//If only added, m_removed[i].size()=0.
		//m_added.size()>0 and m_removed[i].size()>0 means that
		//m_removed[i] is replaced by m_added.

	std::vector<UniqueGLAttrib> m_added;
		//MGGLAttrib's that are added to the target. If only removed, m_added.size()=0.

	MGGEL_TID m_remove_type;
		//When remove action, m_added.size()=m_removed.size()=0
		//and m_remove_type is set initially.
		//In Do() operation the removed MGGLAttrib will be set in m_removed.

	
	//define document action.
	void do_action(ACTION_TYPE a);
};

#endif
