#ifndef __MOVECELLHPP__
#define __MOVECELLHPP__

#include <stack>
#include <queue>

struct PATHCELLELEMENT
{
	int x,y;
	bool operator< (const PATHCELLELEMENT& p1) const;
	bool operator== (const PATHCELLELEMENT& p1) const;
	PATHCELLELEMENT (int nx,int ny) { x = nx; y = ny;}
	PATHCELLELEMENT (void) { x = -1; y = -1; }
};

const int OFFSIZECELL = 8;
const	int offsetcell[OFFSIZECELL][2] = {
	{-1,-1},
	{-1,0},
	{-1,1},
	{0,-1},
	{0,1},
	{1,-1},
	{1,0},
	{1,1}
	};

class CALCCELLELEMENT : public FibHeapNode
{
private:
	static FixedHeap<CALCCELLELEMENT> m_EmptyCalcCellElement;

public:
	int x,y;
	CALCCELLELEMENT (int nx,int ny) { x = nx; y = ny;}
	CALCCELLELEMENT (void) { x = -1; y = -1; }
    virtual void operator =(FibHeapNode& RHS);
    virtual bool operator ==(FibHeapNode& RHS);
    virtual bool operator <(FibHeapNode& RHS);

//    static CALCELEMENT *GetBlankElement (void) { return (CALCELEMENT *) m_EmptyCalcElement.Alloc (); }
//    static void DoneElement (CALCELEMENT *oldelem)  { m_EmptyCalcElement.Free (oldelem); }

//	void *operator new (size_t size) {return GetBlankElement (); }
//	void operator delete (void *value,size_t size) { DoneElement ((CALCELEMENT *) value); }
};

class CCellPath
{
private:
	std::stack<PATHCELLELEMENT> m_Path;
	CPoint m_Start;							// in local coordinates for start point, has to be within the cell
	std::vector<CPoint> m_End;	// in local coordinates for the end point, has to be within the cell, vector for edge valid cells
	CPoint m_RealEnd;
	int m_StartArea;						// areaid for the start point in the cell list
	int m_EndArea;							// areaid for the end point in the cell list
	int m_EndAreaOther;				// the areaid for the next cell in the move list, if zero this is the last cell in the list
	CPoint m_Cell;							// what cell this path is within

	bool ValidEnd (const CPoint& where)
	{
		std::vector<CPoint>::iterator iter;
	
		iter = m_End.begin ();
		while (iter != m_End.end ())
		{
			if ((*iter) == where)
				return true;
			iter++;
		}
		return false;
	}
	bool ValidEnd (int wx,int wy)
	{ return ValidEnd (CPoint (wx,wy)); }

	float GetOneCost (int sx,int sy,int dx,int dy);
	float PathCostGuess (int sx,int sy,int dx,int dy);

public:
	CCellPath (CPoint start,CPoint cell,int endarea,int endareaother,int edge);		// for edge to edge movement, or inside to edge movement	start is in global coordinates
	CCellPath (CPoint start,CPoint cell,CPoint end);		// for edge to inside movement		// start and end are global coordinates
	~CCellPath (void);

	bool CalcPath (void);
	CPoint StartPoint (void) const
	{ return m_Start; }
	CPoint EndPoint (void) const
	{ return m_RealEnd; }
	int StartArea (void) const
	{ return m_StartArea; }
	int EndArea (void) const
	{ return m_EndArea; }
	int EndAreaOther (void) const
	{ return m_EndAreaOther; }

	void operator =(const CCellPath& RHS)
	{
		m_Path = RHS.m_Path;
		m_Start = RHS.m_Start;
		m_End = RHS.m_End;
		m_RealEnd = RHS.m_RealEnd;
		m_StartArea = RHS.m_StartArea;
		m_EndArea = RHS.m_EndArea;
		m_EndAreaOther = RHS.m_EndAreaOther;
		m_Cell = RHS.m_Cell;
	}

};

void InitMoveCellData (void);


#endif

