package main

import (
	"context"
	"fmt"
  "net"
  "math"
  

	"github.com/fastly/compute-sdk-go/fsthttp"
  "github.com/fastly/compute-sdk-go/geo"
)

const BackendName = "origin_0"

func main() {
	fsthttp.ServeFunc(func(ctx context.Context, w fsthttp.ResponseWriter, r *fsthttp.Request) {
		// This example calculates the distance between a client's physical location
    // and a fixed location, Paris.

    // Latitude and longiture of Paris.
    const lat1 = 48.8566
    const long1 = 2.3522
    
    // Get client IP address.
    clientIP := net.ParseIP(r.RemoteAddr)
    data, err := geo.Lookup(clientIP)
    if err != nil {
      panic(err)
    }
    // Get the client's latitude and longitude.
    lat2 := data.Latitude
    long2 := data.Longitude

    // Calculate the distance between the two locations.
    distance := haversinceDistanceBetweenPoints(lat1, long1, lat2, long2)
    
    w.Header().Set("Content-Type", "text/html; charset=utf-8")
    // Return the distance in the response body
    fmt.Fprintln(w, fmt.Sprintf("You are %.2f km from Paris.", distance) )
    w.WriteHeader(fsthttp.StatusOK)
    return
	})
}

// The Haversine Formula is used to calculate the distance in kilometers.
// Info: https://en.wikipedia.org/wiki/Haversine_formula
func haversinceDistanceBetweenPoints(lat1, long1, lat2, long2 float64) float64 {
	// Phi is the latitude and lambda is the latidude in radians respectively
	// Radius of the Earth in kilometers
	const R = 6371
	// Convert degress to radians
	const toRadian = math.Pi / 180

	// Convert latitudes in degrees to radians
	phi1 := lat1 * toRadian
	phi2 := lat2 * toRadian

	deltaPhi := (lat1 - lat2) * toRadian
	deltaLambda := (long1 - long2) * toRadian

	a := math.Pow(math.Sin(deltaPhi/2.0), 2) + math.Cos(phi1)*math.Cos(phi2)*math.Pow(math.Sin(deltaLambda/2.0), 2)
	c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))
	return R * c
}