/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/********************************************************************/
/// GelAction.h: interface for the mgGelAction class.
/// mgGelAction provides MGGel Undomanager's actions. Especially,
/// std::vector<SYSGLS> m_sysgls_vector functions.
/// m_sysgls_vector[i] corresponds to m_target_gels[i] for 0<=i<m_target_gels.size().

#if !defined(_mgGelACTION_HH_)
#define _mgGelACTION_HH_

#pragma once

#include "fugenDoc.h"
#include <vector>
#include "mg/GelPositions.h"

class MGOpenGLView;
class CUndoManager;
class mgSysGL;
class MGPickObjects;

/// GelAction.h: interface for the mgGelAction class.
/// mgGelAction provides MGGel Undomanager's actions. Especially,
class mgGelAction{
public:

	typedef std::vector<mgSysGL*> SYSGLS;

	typedef std::vector<mgSysGL*>::iterator              gl_iterator;
	typedef std::vector<mgSysGL*>::reverse_iterator      reverse_gl_iterator;
	typedef std::vector<mgSysGL*>::reference             gl_reference;
	typedef std::vector<mgSysGL*>::size_type             gl_size_type;

	typedef std::vector<mgSysGL*> SYSGLS;
	typedef std::vector<SYSGLS>::iterator              gls_iterator;
	typedef std::vector<SYSGLS>::reverse_iterator      reverse_gls_iterator;
	typedef std::vector<SYSGLS>::reference             gls_reference;
	typedef std::vector<SYSGLS>::size_type             gls_size_type;

	///コンストラクタ
	mgGelAction(fugenDoc* doc=0):m_doc(doc){;};
	///コンストラクタ
	mgGelAction(const MGGelPosition& target,fugenDoc* doc=0);
	///コンストラクタ
	mgGelAction(const MGGelPositions& targets,fugenDoc* doc=0);
	///デストラクタ
	~mgGelAction();

	///Get the glview of the doc.
	MGOpenGLView& glview()const;

	///Add the target gels into the document.
	///appendCurrent specifies if the added object be appended
	///to the current objects(that are hilighted).
	//When appendCurrent=true, the objects will be appended to the currrent objects.
	///Else, the objects will be the only current ones.
	void add_doc(bool appendCurrent=true);

	///Add the target gels' view.
	void add_view();

	///Copy gelAction2's sysgl replacing the gel pointer from gelAction2's gel
	///to this gel.
	void copy_sysgl(const mgGelAction& gelAction2);

	///Delete the target gels from the document.
	void delete_doc();

	///Delete the target gels' view.
	void delete_view();

	fugenDoc* document()const{return m_doc;};
	MGGelPositions& target_gels(){return m_target_gels;};
	const MGGelPositions& target_gels()const{return m_target_gels;};

	///delete the gel objects in m_target_gels.
	void delete_target_gels();

	///Push back a target gel position
	void push_back_gelp(const MGGelPosition& target);

	///Replace this GelAction's display list with to_add's.
	///Delete the display lists of this action and add into to_add.
	///The display lists of mgSysGL will be also replaced.
	void replace_display_list(
		mgGelAction& to_add
	);

	void set_doc(fugenDoc* doc){m_doc=doc;};
	
	///append functions to m_sysgls_vector.
	///All of the ownership of mgSysGL* of functions are transfered to this action.
	void sysgls_push_back(std::vector<UniqueSysGL>&& functions);

	///clear m_sysgls_vector;
	void sysgls_clear_vector();

	size_t sysgls_vector_size(){return m_sysgls_vector.size();};
	SYSGLS& sysgls(size_t i){return m_sysgls_vector[i];};
	const SYSGLS& sysgls(size_t i)const{return m_sysgls_vector[i];};
	SYSGLS& sysgls_back(){return m_sysgls_vector.back();};
	const SYSGLS& sysgls_back()const{return m_sysgls_vector.back();};
	void sysgls_pop_back(){m_sysgls_vector.pop_back();};

private:
	//The target document.
	fugenDoc* m_doc;

	//Target gels. When add, gels to add. When remove, gels to remove. And so on...
	MGGelPositions m_target_gels;

	//mgSysGL* that are displayed for target gels.
	//m_sysgls_vector.size()==0 means no SYSGLS in this vector.
	//When m_sysgls_vector.size()>0, m_sysgls_vector.size()==m_target_gels.size().
	//m_sysgls_vector[i] is the SYSGLS of m_target_gels[i], which may be null vector.
	std::vector<SYSGLS> m_sysgls_vector;
};

#endif
