/**
 * 最初の著者:: トゥイー
 * リポジトリ情報:: $Id: WorkingMemory.hpp 11 2011-05-14 02:11:18Z yutaka_at_home $
 * 著作権:: Copyright (C) Ownway.info, 2011. All rights reserved.
 * ライセンス:: CPL(Common Public Licence)
 */

#ifndef _TOPS_WORKING_MEMORY_HPP_
#define _TOPS_WORKING_MEMORY_HPP_

#include "tops/WMElement.hpp"
#include "tops/common/Printable.hpp"

#include "tops/utilities/CloseContainer.hpp"
#include "tops/utilities/Iterator/MapIterator.hpp"
#include "tops/utilities/Iterator/SharedToPointerIterator.hpp"

#include <string>

namespace tops {

	/**
	 * ワーキングメモリです。
	 *
	 * @author トゥイー
	 */
	class WorkingMemory : public Printable {
	private:
		typedef Utility::CloseMultiMap<std::string, WMElementPtr> ElementMap;
		typedef ElementMap::iterator InnerMapIterator;
		typedef ElementMap::const_iterator ConstInnerMapIterator;

		typedef Utility::MapIteratorSecond<InnerMapIterator, WMElementPtr> MapSecondIterator;
		typedef Utility::ConstMapIteratorSecond<ConstInnerMapIterator, WMElementPtr> ConstMapSecondIterator;

		typedef Utility::CloseList<WMElementPtr> ElementList;
		typedef ElementList::iterator InnerIterator;
		typedef ElementList::const_iterator ConstInnerIterator;

	public:
		typedef Utility::SharedToPointerIterator<MapSecondIterator, WMElement> MapIterator;
		typedef Utility::ConstSharedToPointerIterator<ConstMapSecondIterator, WMElement> ConstMapIterator;

		typedef Utility::SharedToPointerIterator<InnerIterator, WMElement> iterator;
		typedef Utility::ConstSharedToPointerIterator<ConstInnerIterator, WMElement> const_iterator;

	private:
		/**
		 * 名前で検索可能なワーキングメモリ要素列です。
		 */
		ElementMap m_namedElements;

		/**
		 * 挿入順序にソーティングされたワーキングメモリ要素列です。
		 */
		ElementList m_orderedElements;

		/**
		 * カウンタです。
		 */
		unsigned long m_count;

	public:
		/**
		 * ワーキングメモリを構築します。
		 */
		WorkingMemory() : m_count(1) {
		}

		/**
		 * ワーキングメモリを破棄します。
		 */
		~WorkingMemory();

	private:
		WMElement* createWMElement(const FactPtr& fact);

	public:
		/**
		 * 事実を追加します
		 *
		 * @param fact 追加する事実を指定します。
		 *
		 * @return
		 * 追加が成功した場合は、追加されたワーキングメモリ要素を返します。
		 * それ以外の場合はNULLを返します。
		 */
		WMElement* add(const FactPtr& fact);

	public:
		/**
		 * 事実が既に存在するかどうかを判断します。
		 *
		 * @return 存在する場合は対応するワーキングメモリ要素を、存在しない場合はNULLを返します。
		 */
		WMElement* searchFact(const FactPtr& target) const;

	public:
		/**
		 * 空かどうかを判断します。
		 *
		 * @return 空だったらtrueを、空じゃなかったらfalseを返します。
		 */
		bool empty() const;

		/**
		 * サイズを取得します。
		 */
		size_t size() const;

		/**
		 * 指定した名前を持つ要素のサイズを取得します。
		 */
		size_t size(const std::string& name) const;

	public:
		/**
		 * 全要素列の先頭を示す反復子を取得します。
		 */
		iterator begin();

		/**
		 * 全要素列の先頭を示す反復子を取得します。
		 */
		const_iterator begin() const;

		/**
		 * 全要素列の末尾を示す反復子を取得します。
		 */
		iterator end();

		/**
		 * 全要素列の末尾を示す反復子を取得します。
		 */
		const_iterator end() const;

	public:
		/**
		 * 指定した名前を示す最初の要素を取得します。
		 */
		ConstMapIterator lower_bound(const std::string& name) const;

		/**
		 * 全要素列の末尾を示す反復子を取得します。
		 */
		ConstMapIterator endMap() const;

	public:
		/**
		 * 名前で要素を絞り込みます。
		 *
		 * @param name 絞り込むために使用する名前を指定します。
		 */
		std::pair<MapIterator, MapIterator> range(const std::string& name);

		/**
		 * 名前で要素を絞り込みます。
		 *
		 * @param name 絞り込むために使用する名前を指定します。
		 */
		std::pair<ConstMapIterator, ConstMapIterator> range(const std::string& name) const;

	public:
		/**
		 * ストリームに出力します。
		 */
		void print(std::ostream& stream) const;
	};

}  // namespace tops

#endif
