/******************************************************************************  		
 * Company:         SINED GmbH
 * Author:          Andriy Kurhanevych
 * Created:         12.02.2013
 * Last modified:   $Modtime: 15.02.13 22:40 $
 * Purpose:         Declaration of the Polyline class
 ******************************************************************************/

#pragma once 
#ifndef POLYGONLIBRARY_POLYLINE_H
#define POLYGONLIBRARY_POLYLINE_H

namespace PolygonLibrary
{ 
	class  Point;
	class  Rectangle;
	class  Node;

	//////////////////////////////////////////////////////////////////////////
	/// Represents a polygonal chain defined as an ordered collection of vertices 
	/// sequentially connected with line segments. 
	/// The vertices are defined as pointers to Node objects of the Topology
	/// the Polyline belongs to.
	//////////////////////////////////////////////////////////////////////////
	class Polyline
	{
	
	// ------------------------------ Interface -------------------------------
	public:
			
		// --- Node collection ---
				
		/// Returns the count of Node pointers in the Polyline.
		int   NodeCount() const;

		/// Returns the Node pointer at the specified index.
		/// @exception Exceptions::ArgumentoutOfRangeException
		Node* NodeAt(int nIndex) const;
		
		/// Sets the Node pointer at the specified index to the specified value, 
		/// that must point to a Node belonging to the same Topology as this Polyline.
		/// @exception Exceptions::ArgumentoutOfRangeException
		/// @exception Exceptions::ArgumentException
		/// @exception Exceptions::InvalidOperationException - if the Polygon is not editable
		void  SetNodeAt(int nIndex, Node* pNode);

		/// Adds the specified Node pointer to the end of the Polyline's Node collection.
		/// The specified Node pointer must refer to a Node belonging to the same Topology as this Polyline. 
		/// @exception Exceptions::ArgumentException
		/// @exception Exceptions::InvalidOperationException - if the Polyline is not editable
		void  AddNode(Node* pNode);
		
		/// Adds the pointer to the Topology's Node at the specified location 
		/// to the end of the Polyline's Node collection.
		/// Creates new Node in the Topology if there is no Node at the location.
		/// @exception Exceptions::InvalidOperationException - if the Polyline is not editable
		void  AddNode(Point point);

		/// Inserts the specified Node pointer into the Polyline's Node collection at the specified index,
		/// shifting up the existing item at the specified index and all subsequent items.
		/// The specified Node pointer must refer to a Node belonging to the same Topology as this Polyline.
		/// @exception Exceptions::ArgumentoutOfRangeException
		/// @exception Exceptions::ArgumentException
		/// @exception Exceptions::InvalidOperationException - if the Polyline is not editable
		void  InsertNode(int nIndex, Node* pNode);
		
		/// Inserts the pointer to the Topology's Node at the specified location into the Polyline's Node collection
		/// at the specified index, shifting up the existing item at the specified index and all subsequent items.
		/// Creates new Node in the Topology if there is no Node at the location.
		/// @exception Exceptions::ArgumentoutOfRangeException
		/// @exception Exceptions::InvalidOperationException - if the Polyline is not editable
		void  InsertNode(int nIndex, Point point);
		
		/// Removes the Node pointer at the specified index from the Polyline's Node collection 
		/// shifting down all subsequent items. Deletes the Node if there is mo more pointer to it in any Polyline.
		/// @exception Exceptions::ArgumentoutOfRangeException
		/// @exception Exceptions::InvalidOperationException - if the Polyline is not editable
		void  RemoveNode(int nIndex);
		
		// --- Other attributes --- 

		/// Returns the length of the polyline.
		double    Length() const;

		/// Returns the bounding box of the polyline.   
		Rectangle Bounds() const;
	
		// --- Operations ---	
		
		/// Returns the index of the first occurrence of the specified Node in the Polyline's Node collection, 
		/// or -1 if the Node doesn't belong to the Polyline.
		int IndexOf(const Node* pNode) const;

		/// Locates the node of the polyline closest to the specified point 
		/// and being within the specified tolerance distance from the point.
		/// Returns the index of the located Node or -1 if no node of the polyline is contained in the circular area. 
		int IndexOfNodeAtLocation(const Point& point, const double dToleranceDistance) const;
		
		// --- disable construction, destruction, copying, assignment ---
	protected:
		Polyline();
		Polyline(const Polyline&);
		~Polyline();
		Polyline& operator=(const Polyline&);
	
	private:
	// --------------------------- Implementation ------------------------------
		friend class PolylineImpl;
		//friend class PolylineEnumerator;
		friend class PolylineLayerImpl;
		friend class PolygonOperations;
		friend class PolygonOperationsImpl;

		const PolylineImpl* impl() const; 
		PolylineImpl*       impl(); 
	};

}
#endif