#if !defined ATS_OBSERVER_H
#define ATS_OBSERVER_H

#include <list>
#include <algorithm>

/*********************************************************************
* Obseverパターン
*
**********************************************************************/

namespace ats
{
	// オブサーバー(被通知側) ---------------------------------------------------
	template<class T>
	class Observer
	{
	public:
		Observer() {};
		virtual ~Observer() {};
		virtual void Update(T&) = 0;
	};

	// サブジェクト(通知側) -----------------------------------------------------
	template<class T>
	class Subject
	{
	private:
		std::list <Observer<T>*> m_obs;

	public:
		Subject () {};
		virtual ~Subject () {};

		virtual void Attach (Observer<T>* obs);
		virtual void Detach (Observer<T>* obs);
		virtual void Notify(T&);
		//get_state();
	};

	// implementation -----------------------------------------------------------------------

	// 登録 -------------------------------------------------------------------
	template<class T>
	void Subject<T>::Attach(Observer<T>* obs)
	{
		m_obs.push_back(obs);
	}

	// 登録抹消 ---------------------------------------------------------------
	template<class T>
	void Subject<T>::Detach (Observer<T>* obs)
	{
		using namespace std;
		list<Observer<T>*>::iterator i;
		// 見つからなければend()を返す。
		i = find(m_obs.begin(), m_obs.end(), obs);
		// よって、end()でなければeraseを実行。
		if (m_obs.end() != i)
		{
			m_obs.erase(i);
		}
	}

	// アップデート ----------------------------------------------------------
	template<class T>
	void Subject<T>::Notify(T& send_block)
	{
		typedef std::list<Observer<T>*>::iterator Obs_itr;
		for(Obs_itr i = m_obs.begin(); m_obs.end() != i; i++)
			(*i)->Update(send_block);
	}
}

#endif // #if !defined ATS_OBSERVER_H
