// WireVertex.h
// e.moon 6may99
//
// PURPOSE
//   Describes a relative position of an endpoint of
//   a wire segment.
//
//   Each vertex contains:
//   * row and column: these indicate the NodeRow/NodeColumn
//     from which the position is based
//   * x offset type:  indicates a position relative to the
//                     given column.  May be one of:
//                     LEFT_GUTTER_COLUMN
//                     NODE_INPUT_JACK
//                     NODE_OUTPUT_JACK
//                     RIGHT_GUTTER_COLUMN
//
//   * x offset index: indicate a further offset within a
//                     GutterColumn.
//
//   * y offset type:  indicates a position relative to the given
//                     row.  May be one of:
//                     TOP_GUTTER_ROW
//                     NODE_JACK
//                     BOTTOM_GUTTER_ROW
//
//   * y offset index: indicates an offset within a GutterRow
//                     or NodeRow (in the latter case, this will
//                     be the connection/jack index.)
//
// HISTORY
//					7may99:	reworked offset/index scheme
//   e.moon	6may99:	created

#ifndef __WIREVERTEX_H__
#define __WIREVERTEX_H__

#include <Point.h>
#include <String.h>
#include <limits.h>

#include "cortex_defs.h"
__BEGIN_CORTEX_NAMESPACE


class WireVertex {
public:					// types & constants
	enum x_offset_t {
		LEFT_GUTTER_COLUMN,
		NODE_INPUT_JACK,
		NODE_OUTPUT_JACK,
		RIGHT_GUTTER_COLUMN
	};

	enum y_offset_t {
		TOP_GUTTER_ROW,
		NODE_JACK,
		BOTTOM_GUTTER_ROW
	};

public:					// ctor
	WireVertex() :
		point(s_noPointCached) {}
	
	// +++++ add validation (no diagonal wires,
	//       do general sanity checks)
	WireVertex(
		uint16				_nodeColumn,
		x_offset_t		_columnOffsetType,
		int16					_columnOffsetIndex,
		uint16				_nodeRow,
		y_offset_t		_rowOffsetType,
		int16					_rowOffsetIndex) :

		nodeColumn(_nodeColumn),
		columnOffsetType(_columnOffsetType),
		columnOffsetIndex(_columnOffsetIndex),
		
		nodeRow(_nodeRow),
		rowOffsetType(_rowOffsetType),
		rowOffsetIndex(_rowOffsetIndex),
		
		point(s_noPointCached) {}

public:					// debugging/diagnostics
	BString toString() const {
		BString out("WireVertex (");
		
		out << (int32)nodeColumn << ':' <<
			((columnOffsetType == LEFT_GUTTER_COLUMN) ? "LEFT_GUTTER_COLUMN" :
				(columnOffsetType == NODE_INPUT_JACK) ? "NODE_INPUT_JACK" :
					(columnOffsetType == NODE_OUTPUT_JACK) ? "NODE_OUTPUT_JACK" :
						"RIGHT_GUTTER_COLUMN") << ':' << (int32)columnOffsetIndex << ", ";

		out << (int32)nodeRow << ':' <<
			((rowOffsetType == TOP_GUTTER_ROW) ? "TOP_GUTTER_ROW" :
				(rowOffsetType == NODE_JACK) ? "NODE_JACK" :
					"BOTTOM_GUTTER_ROW") << ':' << (int32)rowOffsetIndex << ')';

		return out;
	}

public:					// members
	uint16				nodeColumn;
	x_offset_t		columnOffsetType;
	int16					columnOffsetIndex;
	
	uint16				nodeRow;
	y_offset_t		rowOffsetType;
	int16					rowOffsetIndex;
	
	// cached 'real position'
	mutable BPoint			point;
	
	// defined in Wire.cpp
	static const BPoint		s_noPointCached;
};

inline bool operator==(const WireVertex& a, const WireVertex& b) {
	return
		a.nodeColumn == b.nodeColumn &&
		a.columnOffsetType == b.columnOffsetType &&
		a.columnOffsetIndex == b.columnOffsetIndex &&
		a.nodeRow == b.nodeRow &&
		a.rowOffsetType == b.rowOffsetType &&
		a.rowOffsetIndex == b.rowOffsetIndex;
}

// 20may99: 'spacial' comparison operator (assumes that
// offset indices operate left->right and up->down.)
// Has the effect of sorting vertices first by column, then by row,
// then by column offset, then by row offset.  Whee.

inline bool operator<(const WireVertex& a, const WireVertex& b) {
	if(b.nodeColumn > a.nodeColumn)
		return true;
	else if(a.nodeColumn > b.nodeColumn)
		return false;
		
	// a.nodeColumn == b.nodeColumn
	
	if(b.nodeRow > a.nodeRow)
		return true;
	else if(a.nodeRow > b.nodeRow)
		return false;
	
	// a.nodeRow == b.nodeRow
	
	if(b.columnOffsetType > a.columnOffsetType)
		return true;
	else if(a.columnOffsetType > b.columnOffsetType)
		return false;
		
	// a.columnOffsetType == b.columnOffsetType
	
	if(b.columnOffsetIndex > a.columnOffsetIndex)
		return true;
	else if(a.columnOffsetIndex > b.columnOffsetIndex)
		return false;
		
	// a.columnOffsetIndex == b.columnOffsetIndex

	if(b.rowOffsetType > a.rowOffsetType)
		return true;
	else if(a.rowOffsetType > b.rowOffsetType)
		return false;
		
	// a.rowOffsetType == b.rowOffsetType
	
	if(b.rowOffsetIndex > a.rowOffsetIndex)
		return true;

	return false;
}

__END_CORTEX_NAMESPACE
#endif /* __WIREVERTEX_H__ */
