package game

import (
	"fmt"
	"math"
	"strings"
)

// Vector desribes a 3D vector
type Vector struct {
	X int `json:"x"`
	Y int `json:"y"`
}

// Add adds one vector to another
func (v *Vector) Add(v2 Vector) {
	v.X += v2.X
	v.Y += v2.Y
}

// Added calculates a new vector
func (v Vector) Added(v2 Vector) Vector {
	v.Add(v2)
	return v
}

// Negated returns a negated vector
func (v Vector) Negated() Vector {
	return Vector{-v.X, -v.Y}
}

// Length returns the length of the vector
func (v Vector) Length() float64 {
	return math.Sqrt(float64(v.X*v.X + v.Y*v.Y))
}

// Distance returns the distance between two vectors
func (v Vector) Distance(v2 Vector) float64 {
	// Negate the two vectors and calciate the length
	return v.Added(v2.Negated()).Length()
}

// Multiplied returns the vector multiplied by an int
func (v Vector) Multiplied(val int) Vector {
	return Vector{v.X * val, v.Y * val}
}

// Direction describes a compass direction
type Direction int

const (
	North Direction = iota
	NorthEast
	East
	SouthEast
	South
	SouthWest
	West
	NorthWest
)

// DirectionString simply describes the strings associated with a direction
type DirectionString struct {
	Long  string
	Short string
}

// DirectionStrings is the set of strings for each direction
var DirectionStrings = []DirectionString{
	{"North", "N"},
	{"NorthEast", "NE"},
	{"East", "E"},
	{"SouthEast", "SE"},
	{"South", "S"},
	{"SouthWest", "SW"},
	{"West", "W"},
	{"NorthWest", "NW"},
}

// String converts a Direction to a String
func (d Direction) String() string {
	return DirectionStrings[d].Long
}

// ShortString converts a Direction to a short string version
func (d Direction) ShortString() string {
	return DirectionStrings[d].Short
}

// DirectionFromString gets the Direction from a string
func DirectionFromString(s string) (Direction, error) {
	for i, d := range DirectionStrings {
		if strings.ToLower(d.Long) == strings.ToLower(s) || strings.ToLower(d.Short) == strings.ToLower(s) {
			return Direction(i), nil
		}
	}
	return -1, fmt.Errorf("Unknown direction: %s", s)
}

var DirectionVectors = []Vector{
	{0, 1},  // N
	{1, 1},  // NE
	{1, 0},  // E
	{1, -1}, // SE
	{0, -1}, // S
	{-1, 1}, // SW
	{-1, 0}, // W
	{-1, 1}, // NW
}

// Vector converts a Direction to a Vector
func (d Direction) Vector() Vector {
	return DirectionVectors[d]
}