// WorldIterator.h : Declaration of the cWorldIterator

#ifndef __WORLDITERATOR_H_
#define __WORLDITERATOR_H_

#include "resource.h"       // main symbols

/////////////////////////////////////////////////////////////////////////////
// cWorldIterator
class ATL_NO_VTABLE cWorldIterator : 
	public CComObjectRootEx<CComSingleThreadModel>,
	public CComCoClass<cWorldIterator, &CLSID_WorldIterator>,
	public IDispatchImpl<IWorldIterator, &IID_IWorldIterator, &LIBID_DecalFilters>
{
public:
	cWorldIterator()
	{
	}

DECLARE_REGISTRY_RESOURCEID(IDR_WORLDITERATOR)
DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(cWorldIterator)
	COM_INTERFACE_ENTRY(IWorldIterator)
	COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()

public:
	class cMatch
	{
	public:
		cMatch() {};
		virtual ~cMatch() {};
	
		virtual bool match(cWorldDataMap::iterator i) = 0;
		virtual cWorldDataMap::iterator end() = 0;
		virtual cWorldDataMap::iterator begin() = 0;
		virtual void reset() {};
	};

	class cMatchName : public cMatch
	{
	private:
		cWorldDataMap *m_list;
		std::string m_name;
	public:
		cMatchName(cWorldDataMap *list, std::string name) : m_list(list), m_name(name) {};
		virtual bool match(cWorldDataMap::iterator i) {
			cWorldData *pData = i->second;
			return (!m_name.compare(pData->m_strName));
		};
		virtual cWorldDataMap::iterator end() { return m_list->end(); };
		virtual cWorldDataMap::iterator begin() { return m_list->begin(); };
	};

	class cMatchNameSubstring : public cMatch
	{
	private:
		cWorldDataMap *m_list;
		std::string m_name;
	public:
		cMatchNameSubstring(cWorldDataMap *list, std::string name) : m_list(list), m_name(name) {};
		virtual bool match(cWorldDataMap::iterator i) {
			cWorldData *pData = i->second;
			return (pData->m_strName.find(m_name, 0) != std::string::npos);
		};
		virtual cWorldDataMap::iterator end() { return m_list->end(); };
		virtual cWorldDataMap::iterator begin() { return m_list->begin(); };
	};

	class cMatchContainer : public cMatch
	{
	private:
		cWorldDataMap *m_list;
		long m_container;
	public:
		cMatchContainer(cWorldDataMap *list, long container) : m_list(list), m_container(container) { };
		virtual bool match(cWorldDataMap::iterator i) {
			cWorldData *pData = i->second;
			return (m_container == pData->m_dwContainer);
		};
		virtual cWorldDataMap::iterator end() { return m_list->end(); };
		virtual cWorldDataMap::iterator begin() { return m_list->begin(); };
	};

	class cMatchLandscape : public cMatch
	{
	private:
		cWorldDataMap *m_list;
		
	public:
		cMatchLandscape(cWorldDataMap *list) : m_list(list) {};
		virtual bool match(cWorldDataMap::iterator i) {
			cWorldData *pData = i->second ;
			if (pData->m_dwContainer == 0) return true ;
			return false ;
		};
		virtual cWorldDataMap::iterator end() { return m_list->end(); };
		virtual cWorldDataMap::iterator begin() { return m_list->begin(); };
	};

	class cMatchType : public cMatch
	{
	private:
		cWorldDataMap *m_list;
		eObjectType m_type;
	public:
		cMatchType(cWorldDataMap *list, eObjectType type) : m_list(list), m_type(type) {};
		virtual bool match(cWorldDataMap::iterator i) {
			cWorldData *pData = i->second;
			return (m_type == pData->m_eType);
		};
		virtual cWorldDataMap::iterator end() { return m_list->end(); };
		virtual cWorldDataMap::iterator begin() { return m_list->begin(); };
	};

	class cMatchInventory : public cMatch
	{
	private:
		cWorldDataMap *m_list;
		
	public:
		cMatchInventory(cWorldDataMap *list) : m_list(list) {};
		virtual bool match(cWorldDataMap::iterator i) {
			cWorldData *pData = i->second ;
			if (pData->m_dwContainer == m_list->player()) return true ;
			cWorldDataMap::iterator iData = m_list->find(pData->m_dwContainer);
			if (iData != m_list->end()) {
				return iData->second->m_dwContainer == m_list->player() ;
			}
			return false ;
		};
		virtual cWorldDataMap::iterator end() { return m_list->end(); };
		virtual cWorldDataMap::iterator begin() { return m_list->begin(); };
	};

	class cMatchOwner : public cMatch
	{
	private:
		cWorldDataMap *m_list;
		long m_owner;
	public:
		cMatchOwner(cWorldDataMap *list, long owner) : m_list(list), m_owner(owner) { };
		virtual bool match(cWorldDataMap::iterator i) {
			cWorldData *pData = i->second ;
			if (pData->m_dwContainer == m_owner) return true ;
			cWorldDataMap::iterator iData = m_list->find(pData->m_dwContainer);
			if (iData != m_list->end()) {
				return iData->second->m_dwContainer == m_owner ;
			}
			return false ;
		};
		virtual cWorldDataMap::iterator end() { return m_list->end(); };
		virtual cWorldDataMap::iterator begin() { return m_list->begin(); };
	};

	class cMatchAll : public cMatch
	{
	private:
		cWorldDataMap *m_list;
	public:
		cMatchAll(cWorldDataMap *list) : m_list(list) {};
		virtual bool match(cWorldDataMap::iterator i) { return true; };
		virtual cWorldDataMap::iterator end() { return m_list->end(); };
		virtual cWorldDataMap::iterator begin() { return m_list->begin(); };
	};

	typedef std::list< cMatch * > cMatchList;

	~cWorldIterator()
	{
		for (cMatchList::iterator i = m_compares.begin(); i != m_compares.end(); i++)
			delete (*i);
	}

	// IWorldIterator
	void Initialize(cWorldDataMap *pMap);

	STDMETHOD(ByAll)();
	STDMETHOD(ByInventory)();
	STDMETHOD(ByLandscape)();
	STDMETHOD(ByContainer)(long nContainer);
	STDMETHOD(ByOwner)(long nOwner);
	STDMETHOD(ByNameSubstring)(BSTR strSubstring);
	STDMETHOD(ByName)(BSTR strName);
	STDMETHOD(ByType)(enum eObjectType Type);

	STDMETHOD(Pop)();
	STDMETHOD(Reset)();

	STDMETHOD(get_Next)(/*[out]*/ IWorldObject **ppObject, /*[out, retval]*/ VARIANT_BOOL *pVal);
	STDMETHOD(get_Count)(/*[out, retval]*/ long *pVal);
	STDMETHOD(get_Next_Old)(/*[out, retval]*/ IWorldObject **pVal);
	STDMETHOD(get_Quantity)(/*[out, retval]*/ long *pVal);
	
	cWorldDataMap *m_objects;
	cWorldDataMap::iterator	m_i;
	cMatchList m_compares;
};

#endif //__WORLDITERATOR_H_
