//-----------------------------------------------------------------------------
//
//  $Logfile:: /game/path.h                                                   $
// $Revision:: 2                                                              $
//   $Author:: Burgermac                                                      $
//     $Date:: 12/27/00 6:49 PM                                               $
//
// Copyright (C) 1997 by Ritual Entertainment, Inc.
// All rights reserved.
//
// This source is may not be distributed and/or modified without
// expressly written permission by Ritual Entertainment, Inc.
//
// DESCRIPTION:
//

#ifndef __PATH_H__
#define __PATH_H__

#include "g_local.h"
#include "class.h"
#include "container.h"
//#include "navigate.h"

//
// Exported templated classes must be explicitly instantiated
//

class Path : public Class
{
private:
	Container<PathNodePtr>  pathlist;
	Container<float>          distanceToNextNode;
	Container<Vector>         dirToNextNode;
	float pathlength;
	PathNodePtr from;
	PathNodePtr to;
	int nextnode;

public:
	CLASS_PROTOTYPE( Path );

	Path();
	Path( int numnodes );
	void            Clear( void );
	void            Reset( void );
	void            AddNode( PathNode* node );
	PathNode*       GetNode( int num );
	PathNode*       NextNode( void );
	PathNode*       NextNode( PathNode* node );
	Vector      ClosestPointOnPath( const Vector& pos );
	float           DistanceAlongPath( const Vector& pos );
	Vector      PointAtDistance( float dist );
	PathNode*       NextNode( float dist );
	void            DrawPath( float r, float g, float b, float time );
	int         NumNodes( void );
	float           Length( void );
	PathNode*       Start( void );
	PathNode*       End( void );
	virtual void Archive( Archiver& arc );
	virtual void Unarchive( Archiver& arc );
};

inline void Path::Archive( Archiver& arc )
{
	PathNodePtr ptr;
	int i, num;

	Class::Archive( arc );

	num = pathlist.NumObjects();
	arc.WriteInteger( num );
	for( i = 1; i <= num; i++ )
	{
		ptr = pathlist.ObjectAt( i );
		arc.WriteSafePointer( ptr );
	}

	arc.WriteFloat( pathlength );
	arc.WriteSafePointer( from );
	arc.WriteSafePointer( to );
	arc.WriteInteger( nextnode );
}

inline void Path::Unarchive( Archiver& arc )
{
	PathNodePtr* ptr;
	PathNodePtr node;
	float len;
	Vector dir;
	int i, num;

	Class::Unarchive( arc );

	pathlist.FreeObjectList();
	distanceToNextNode.FreeObjectList();
	dirToNextNode.FreeObjectList();

	num = arc.ReadInteger();
	for( i = 1; i <= num; i++ )
	{
		pathlist.AddObject( node );
		ptr = pathlist.AddressOfObjectAt( i );
		arc.ReadSafePointer( ptr );
	}

	// Recalculate the path distances and directions
	// only go up to the node before the last node.
	for( i = 1; i < num; i++ )
	{
		dir = pathlist.ObjectAt( i + 1 )->worldorigin - pathlist.ObjectAt( i )->worldorigin;
		len = dir.length();
		dir *= 1 / len;

		distanceToNextNode.SetObjectAt( i, len );
		dirToNextNode.SetObjectAt( i, dir );
	}

	if( num )
	{
		// special case for last node
		len = 0;
		distanceToNextNode.AddObject( len );
		dirToNextNode.AddObject( vec_zero );
	}

	pathlength = arc.ReadFloat();
	arc.ReadSafePointer( &from );
	arc.ReadSafePointer( &to );
	nextnode = arc.ReadInteger();
}


typedef SafePtr<Path> PathPtr;

#endif /* path.h */
