package routing

import (
	
	
)

type Route struct {
	GEdge    *layoutgraph.Edge
	OVGNodes []*OVGNode
	FromPort geo.Point
	ToPort   geo.Point
}

func ( *Route) () []*geo.Point {
	 := make([]*geo.Point, 0)

	 = append(, .OVGNodes[1].Point.Copy())
	for  := 2;  < len(.OVGNodes)-2; ++ {
		 := .OVGNodes[-1].Point
		 := .OVGNodes[].Point
		 := .OVGNodes[+1].Point
		if (.X == .X) && (.X != .X) {
			 = append(, .Copy())
		} else if (.Y == .Y) && (.Y != .Y) {
			 = append(, .Copy())
		}
	}
	 = append(, .OVGNodes[len(.OVGNodes)-2].Point.Copy())
	return 
}

// The entire route is colinear
func ( *Route) (,  *OVGNode) bool {
	if .Y == .Y {
		 := .Y
		,  := .X, .X
		if  <  {
			,  = , 
		}
		for  := 1;  < len(.OVGNodes)-2; ++ {
			,  := .OVGNodes[], .OVGNodes[+1]
			if .Y !=  || .Y !=  {
				return false
			}
			,  := .X, .X
			if  <  {
				,  = , 
			}
			if  <  ||  >  {
				return false
			}
		}
		return true
	}

	if .X == .X {
		 := .X
		,  := .Y, .Y
		if  <  {
			,  = , 
		}
		for  := 1;  < len(.OVGNodes)-2; ++ {
			,  := .OVGNodes[], .OVGNodes[+1]
			if .X !=  || .X !=  {
				return false
			}
			,  := .Y, .Y
			if  <  {
				,  = , 
			}
			if  <  ||  >  {
				return false
			}
		}
		return true
	}

	return false
}

// isOpposingColinear returns true if the segment <from, to> spans colinearly in the opposite direction to any segment of the route
// This only applies to routes which are directed, otherwise there is no notion of opposite
// If the segments share a single endpoint, that doesn't count
// TODO: allow bidirectional edges with different arrowheads to overlap in the
// same direction; see edgeCanOverlapEdges.
func ( *Route) (,  *OVGNode) bool {
	if !.GEdge.IsDirected() {
		return false
	}
	if .Y == .Y {
		 := .Y
		,  := .X, .X
		if  <  {
			,  = , 
		}
		for  := 0;  < len(.OVGNodes)-2; ++ {
			if .OVGNodes[+1].Y !=  {
				++
				continue
			}
			if .OVGNodes[].Y !=  {
				continue
			}
			,  := .OVGNodes[], .OVGNodes[+1]
			if .X != .X {
				if .X < .X {
					if  < .X || .X <  {
						continue
					}
				} else {
					if  < .X || .X <  {
						continue
					}
				}

				,  := .X, .X
				if  <  {
					,  = , 
				}

				if  <= .X && .X <=  && (.X <  ||  < .X) {
					if nonNilEquals(.Point, .Point) || nonNilEquals(.Point, .Point) {
						return false
					}
				} else if  <= .X && .X <=  && (.X <  ||  < .X) {
					if nonNilEquals(.Point, .Point) || nonNilEquals(.Point, .Point) {
						return false
					}
				}

				if (.X > .X) && (.X < .X) {
					return true
				} else if (.X < .X) && (.X > .X) {
					return true
				}
			}
		}
	} else if .X == .X {
		 := .X
		,  := .Y, .Y
		if  <  {
			,  = , 
		}
		for  := 0;  < len(.OVGNodes)-2; ++ {
			if .OVGNodes[+1].X !=  {
				++
				continue
			}
			if .OVGNodes[].X !=  {
				continue
			}
			,  := .OVGNodes[], .OVGNodes[+1]

			if .Y != .Y {
				if .Y < .Y {
					if  < .Y || .Y <  {
						continue
					}
				} else {
					if  < .Y || .Y <  {
						continue
					}
				}

				,  := .Y, .Y
				if  <  {
					,  = , 
				}

				if  <= .Y && .Y <=  && (.Y <  ||  < .Y) {
					if nonNilEquals(.Point, .Point) || nonNilEquals(.Point, .Point) {
						return false
					}
				} else if  <= .Y && .Y <=  && (.Y <  ||  < .Y) {
					if nonNilEquals(.Point, .Point) || nonNilEquals(.Point, .Point) {
						return false
					}
				}

				if (.Y > .Y) && (.Y < .Y) {
					return true
				} else if (.Y < .Y) && (.Y > .Y) {
					return true
				}
			}
		}
	}

	return false
}

// A route can swap edges with another route if:
// - The two endpoints are the same nodes
// - No other edges are using the ports
//   - TODO can iterate on this to allow some instances
//
// - The two endpoints is not diagonal
// - The ports that the two routes are connected to on each node are on the same side
// TODO consider min distance for labels
// Not self-route
func ( *Route) ( *Route,  []*Route,  workBudget) (bool, error) {
	if .GEdge.From == .GEdge.To {
		return false, nil
	}
	if .GEdge.From == .GEdge.To {
		return false, nil
	}
	if !((.GEdge.From == .GEdge.From && .GEdge.To == .GEdge.To) ||
		(.GEdge.From == .GEdge.To && .GEdge.To == .GEdge.From)) {
		return false, nil
	}

	if .GEdge.From.Orientation(.GEdge.To).IsDiagonal() {
		return false, nil
	}

	if .GEdge.From == .GEdge.From && .GEdge.To == .GEdge.To {
		if .GEdge.From.Orientation(.GEdge.To).IsVertical() {
			if .FromPort.Y != .FromPort.Y {
				return false, nil
			}
			if .ToPort.Y != .ToPort.Y {
				return false, nil
			}
		}
		if .GEdge.From.Orientation(.GEdge.To).IsHorizontal() {
			if .FromPort.X != .FromPort.X {
				return false, nil
			}
			if .ToPort.X != .ToPort.X {
				return false, nil
			}
		}
	}

	for ,  := range  {
		if  != nil {
			if  := .step();  != nil {
				return false, 
			}
		}
		if  ==  ||  ==  {
			continue
		}
		if .FromPort == .FromPort || .FromPort == .ToPort {
			return false, nil
		}
		if .ToPort == .FromPort || .ToPort == .ToPort {
			return false, nil
		}
		if .FromPort == .FromPort || .FromPort == .ToPort {
			return false, nil
		}
		if .ToPort == .FromPort || .ToPort == .ToPort {
			return false, nil
		}
	}

	return true, nil
}