package geo

import (
	
	
)

type Intersectable interface {
	Intersections(segment Segment) []*Point
}

type Segment struct {
	Start *Point
	End   *Point
}

func (,  *Point) *Segment {
	return &Segment{, }
}

func ( Segment) ( Segment,  bool,  float64) bool {
	if  {
		if math.Min(.Start.Y, .End.Y)-math.Max(.Start.Y, .End.Y) >=  {
			return false
		}
		if math.Min(.Start.Y, .End.Y)-math.Max(.Start.Y, .End.Y) >=  {
			return false
		}
		return true
	} else {
		if math.Min(.Start.X, .End.X)-math.Max(.Start.X, .End.X) >=  {
			return false
		}
		if math.Min(.Start.X, .End.X)-math.Max(.Start.X, .End.X) >=  {
			return false
		}
		return true
	}
}

func ( Segment) ( Segment) bool {
	return IntersectionPoint(.Start, .End, .Start, .End) != nil
}

//nolint:unused
func ( Segment) () string {
	return fmt.Sprintf("%v -> %v", .Start.ToString(), .End.ToString())
}

func ( Segment) ( Segment) []*Point {
	 := IntersectionPoint(.Start, .End, .Start, .End)
	if  == nil {
		return nil
	}
	return []*Point{}
}

// getBounds takes a segment and returns the floor and ceil of where it can shift to
// If there is no floor or ceiling, negative or positive infinity is used, respectively
// The direction is inferred, e.g. b/c the passed in segment is vertical, it's inferred we want horizontal bounds
// buffer says how close the segment can be, on both axes, to other segments given
// .    │              │
// .    │              │
// .    │              │
// .    │              │
// .    │           non-overlap
// .    │
// .    │
// .    │
// .    │     segment
// .    │       │
// .    │       │         ceil
// .    │       │            │
// .            │            │
// . floor      │            │
// .                         │
// .                         │
// .                         │
// .                         │
// NOTE: the assumption is that all segments given are orthogonal
func ( *Segment) ( []*Segment,  float64) (float64, float64) {
	 := math.Inf(1)
	 := math.Inf(-1)
	if .Start.X == .End.X && .Start.Y == .End.Y {
		// single point, no segment
		return , 
	}
	 := .Start.X == .End.X
	for ,  := range  {
		if  {
			// Exclude segments that don't overlap (non-overlap in above diagram)
			if .End.Y < .Start.Y- {
				continue
			}
			if .Start.Y > .End.Y+ {
				continue
			}
			if .Start.X <= .Start.X {
				 = math.Max(, .Start.X)
			}
			if .Start.X > .Start.X {
				 = math.Min(, .Start.X)
			}
		} else {
			if .End.X < .Start.X- {
				continue
			}
			if .Start.X > .End.X+ {
				continue
			}
			if .Start.Y <= .Start.Y {
				 = math.Max(, .Start.Y)
			}
			if .Start.Y > .Start.Y {
				 = math.Min(, .Start.Y)
			}
		}
	}
	return , 
}

func ( Segment) () float64 {
	return EuclideanDistance(.Start.X, .Start.Y, .End.X, .End.Y)
}

func ( Segment) () Vector {
	return NewVector(.End.X-.Start.X, .End.Y-.Start.Y)
}