package arn

import "math"

// EarthRadius is the radius of the earth in kilometers.
const EarthRadius = 6371

// Location ...
type Location struct {
	CountryName string  `json:"countryName"`
	CountryCode string  `json:"countryCode"`
	Latitude    float64 `json:"latitude" editable:"true"`
	Longitude   float64 `json:"longitude" editable:"true"`
	CityName    string  `json:"cityName"`
	RegionName  string  `json:"regionName"`
	TimeZone    string  `json:"timeZone"`
	ZipCode     string  `json:"zipCode"`
}

// IPInfoDBLocation ...
type IPInfoDBLocation struct {
	CountryName string `json:"countryName"`
	CountryCode string `json:"countryCode"`
	Latitude    string `json:"latitude"`
	Longitude   string `json:"longitude"`
	CityName    string `json:"cityName"`
	RegionName  string `json:"regionName"`
	TimeZone    string `json:"timeZone"`
	ZipCode     string `json:"zipCode"`
}

// IsValid returns true if latitude and longitude are available.
func (p *Location) IsValid() bool {
	return p.Latitude != 0 && p.Longitude != 0
}

// Distance calculates the distance in kilometers to the second location.
// Original implementation: https://www.movable-type.co.uk/scripts/latlong.html
func (p *Location) Distance(p2 *Location) float64 {
	dLat := (p2.Latitude - p.Latitude) * (math.Pi / 180.0)
	dLon := (p2.Longitude - p.Longitude) * (math.Pi / 180.0)

	lat1 := p.Latitude * (math.Pi / 180.0)
	lat2 := p2.Latitude * (math.Pi / 180.0)

	a1 := math.Sin(dLat/2) * math.Sin(dLat/2)
	a2 := math.Sin(dLon/2) * math.Sin(dLon/2) * math.Cos(lat1) * math.Cos(lat2)

	a := a1 + a2
	c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))

	return EarthRadius * c
}