#ifndef __AIRAILPATHHPP__
#define __AIRAILPATHHPP__

#pragma warning (disable:4786)
#include "utils\utils.h"
#include <vector>
#include <map>

class CRailNode;

class CRailLink
{
private:

	CRailNode *m_Loc[2];
	float m_Weight;
	bool m_Jump;
public:

	CRailLink (void)
	{
		m_Loc[0] = m_Loc[1] = NULL;
		m_Weight = 0;
		m_Jump = false;
	}
	CRailLink (CRailNode *loc1,CRailNode *loc2,float nweight,bool njump = false)
	{
		m_Loc[0] = loc1;
		m_Loc[1] = loc2;
		m_Weight = nweight;
		m_Jump = njump;
	}
	float Weight (void) const
	{ return m_Weight; }
	bool Jump (void) const
	{ return m_Jump; }
	const CRailNode *Location (int id) const
	{
		assert ((id>=0) && (id<=1));
		return m_Loc[id];
	}
};

class CRailNode
{
private:

	CPoint m_Location;

public:
	CRailNode (CPoint loc);
	~CRailNode (void);

	CPoint Location (void) const
	{ return m_Location; }
};

class CRailGraph
{
private:
	std::map<int,CRailNode *> m_Nodes;
	std::vector<CRailLink *> m_Links;

public:
	CRailGraph (void);
	~CRailGraph (void);

	void AddNode (CRailNode *node,int id);
	void AddLink (CRailLink *link);
	void AddLink (int n1,int n2,float weight,bool jump=false)
	{
		assert (m_Nodes.find (n1) != m_Nodes.end ());
		assert (m_Nodes.find (n2) != m_Nodes.end ());
		AddLink (new CRailLink (m_Nodes[n1],m_Nodes[n2],weight,jump));
	}

	float Connect (CRailNode *src,CRailNode *dest) const;
};

class CRailPath
{
private:
	CPoint m_Start;
	CPoint m_End;

	int m_CurrentLink;

	std::vector<CRailLink *> m_Links;

public:
	CRailPath (CPoint start,CPoint end);
	~CRailPath (void);

	void CalcPath (void);
	const CRailLink *CurrentLink (void) const
	{
		assert (m_CurrentLink >= 0);
		assert (m_CurrentLink < m_Links.size ());
		return m_Links[m_CurrentLink];
	}
	bool NextLink (void)							// true if path still exists
	{
		m_CurrentLink++;
		return m_CurrentLink != m_Links.size ();
	}
};

#endif
														
