#ifndef __OBJECT_LIST_H__
#define __OBJECT_LIST_H__

#include "Object.h"

namespace AScript {

//-----------------------------------------------------------------------------
// Class_List
//-----------------------------------------------------------------------------
class DLLDECLARE Class_List : public Class {
public:
	Class_List(Environment *pEnvOuter);
	virtual bool CastFrom(Environment &env, Signal sig, Value &value);
	virtual Object *CreateDescendant(Environment &env, Signal sig, Class *pClass);
};

//-----------------------------------------------------------------------------
// Object_List
//-----------------------------------------------------------------------------
class DLLDECLARE Object_List : public Object {
public:
	class IteratorEach : public Iterator {
	private:
		Object_List *_pObj;
		ValueList::const_iterator _pValue;
		ValueList::const_iterator _pValueEnd;
	public:
		inline IteratorEach(Object_List *pObj) :
			Iterator(false), _pObj(pObj),
			_pValue(pObj->GetList().begin()), _pValueEnd(pObj->GetList().end()) {}
		inline IteratorEach(Object_List *pObj, size_t offset) :
			Iterator(false), _pObj(pObj),
			_pValue((offset < pObj->GetList().size())?
					pObj->GetList().begin() + offset : pObj->GetList().end()),
			_pValueEnd(pObj->GetList().end()) {}
		inline IteratorEach(Object_List *pObj, size_t offset, size_t cnt) :
			Iterator(false), _pObj(pObj),
			_pValue((offset < pObj->GetList().size())?
					pObj->GetList().begin() + offset : pObj->GetList().end()),
			_pValueEnd((offset + cnt < pObj->GetList().size())?
					pObj->GetList().begin() + offset + cnt : pObj->GetList().end()) {}
		virtual ~IteratorEach();
		virtual bool DoNext(Environment &env, Signal sig, Value &value);
		virtual String ToString(Signal sig) const;
	};
	class IteratorReverse : public Iterator {
	private:
		Object_List *_pObj;
		ValueList::reverse_iterator _pValue;
	public:
		inline IteratorReverse(Object_List *pObj) :
			Iterator(false), _pObj(pObj), _pValue(pObj->GetList().rbegin()) {}
		virtual ~IteratorReverse();
		virtual bool DoNext(Environment &env, Signal sig, Value &value);
		virtual String ToString(Signal sig) const;
	};
	class IteratorRound : public Iterator {
	private:
		Object_List *_pObj;
		int _cnt;
		ValueList::iterator _pValue;
	public:
		inline IteratorRound(Object_List *pObj, int cnt) :
			Iterator(cnt < 0), _pObj(pObj), _pValue(pObj->GetList().begin()), _cnt(cnt) {}
		virtual ~IteratorRound();
		virtual bool DoNext(Environment &env, Signal sig, Value &value);
		virtual String ToString(Signal sig) const;
	};
	class IteratorPingpong : public Iterator {
	private:
		Object_List *_pObj;
		int _cnt;
		bool _stickyFlagL, _stickyFlagR;
		bool _forwardFlag;
		ValueList::iterator _pValueFwd;
		ValueList::reverse_iterator _pValueBwd;
	public:
		inline IteratorPingpong(Object_List *pObj, int cnt, bool stickyFlagL, bool stickyFlagR) :
			Iterator(cnt < 0), _pObj(pObj), _cnt(cnt),
			_stickyFlagL(stickyFlagL), _stickyFlagR(stickyFlagR), _forwardFlag(true),
			_pValueFwd(pObj->GetList().begin()), _pValueBwd(pObj->GetList().rbegin()) {}
		virtual ~IteratorPingpong();
		virtual bool DoNext(Environment &env, Signal sig, Value &value);
		virtual String ToString(Signal sig) const;
	};
	class IteratorFold : public Iterator {
	private:
		Object_List *_pObj;
		size_t _offset;
		size_t _cntPerFold;
		size_t _cntStep;
		bool _listItemFlag;
	public:
		inline IteratorFold(Object_List *pObj, size_t cntPerFold, size_t cntStep, bool listItemFlag) :
			Iterator(false), _pObj(pObj), _offset(0),
			_cntPerFold(cntPerFold), _cntStep(cntStep), _listItemFlag(listItemFlag) {}
		virtual ~IteratorFold();
		virtual bool DoNext(Environment &env, Signal sig, Value &value);
		virtual String ToString(Signal sig) const;
	};
	class IteratorPermutation : public Iterator {
	public:
		typedef std::vector<size_t> IndexList;
	private:
		Object_List *_pObj;
		IndexList _indexList;
		int _cnt;
		bool _validFlag;
	public:
		IteratorPermutation(Object_List *pObj, int cnt);
		~IteratorPermutation();
		virtual bool DoNext(Environment &env, Signal sig, Value &value);
		virtual String ToString(Signal sig) const;
	};
	class IteratorCombination : public Iterator {
	public:
		typedef std::vector<size_t> IndexList;
	private:
		Object_List *_pObj;
		IndexList _indexList;
		int _cnt;
		bool _validFlag;
	public:
		IteratorCombination(Object_List *pObj, int cnt);
		~IteratorCombination();
		virtual bool DoNext(Environment &env, Signal sig, Value &value);
		virtual String ToString(Signal sig) const;
	};
	class Comparator_Ascend {
	public:
		inline bool operator()(const Value *pValue1, const Value *pValue2) const {
			return Value::Compare(*pValue1, *pValue2) < 0;
		}
	};
	class Comparator_Descend {
	public:
		inline bool operator()(const Value *pValue1, const Value *pValue2) const {
			return Value::Compare(*pValue1, *pValue2) > 0;
		}
	};
	class Comparator_Custom {
	private:
		Environment &_env;
		Signal &_sig;
		const Function *_pFunc;
	public:
		inline Comparator_Custom(Environment &env, Signal &sig, const Function *pFunc) :
										_env(env), _sig(sig), _pFunc(pFunc) {}
		bool operator()(const Value *pValue1, const Value *pValue2) const;
	};
public:
	AScript_DeclareObjectAccessor(List)
public:
	typedef std::vector<size_t> IndexList;
	class ValueVisitor_Index : public ValueVisitor {
	private:
		Environment &_env;
		const ValueList &_valList;
		IndexList _indexList;
	public:
		inline ValueVisitor_Index(Environment &env, const ValueList &valList) :
											_env(env), _valList(valList) {}
		virtual void Visit(Signal sig, const Value &value);
		inline IndexList &GetIndexList() { return _indexList; }
	};
private:
	ValueList _valList;
public:
	inline Object_List(Class *pClass) : Object(pClass) {}
	inline Object_List(Environment &env) : Object(env.LookupClass(VTYPE_List)) {}
	inline Object_List(Environment &env, size_t n, const Value &value) :
						Object(env.LookupClass(VTYPE_List)), _valList(n, value) {}
	inline Object_List(Environment &env, const ValueList &valList) :
						Object(env.LookupClass(VTYPE_List)), _valList(valList) {}
	inline Object_List(const Object_List &obj) :
									Object(obj), _valList(obj._valList) {}
	virtual Object *Clone() const;
	static inline Object_List *IncRef(const Object_List *pObj) {
		return dynamic_cast<Object_List *>(Object::Reference(pObj));
	}
	inline ValueList &GetList() { return _valList; }
	inline const ValueList &GetList() const { return _valList; }
	virtual Value IndexGet(Signal sig, const Value &valueIdx);
	virtual void IndexSet(Signal sig, const Value &valueIdx, const Value &value);
	virtual Iterator *CreateIterator(Signal sig);
	virtual String ToString(Signal sig, bool exprFlag);
	Object_List *SortRank(Signal sig, const Value &valDirective,
					const ValueList *pValListKey, bool rankFlag, bool stableFlag);
};

}

#endif
