package origin

import (
	"fmt"
	"net/http"
	"net/url"
	"strings"
)

var defaultPorts = map[string]string{
	"http":  "80",
	"https": "443",
}

// UndefinedWebOrigin is returned when a web origin is not parsable.
var UndefinedWebOrigin = "null"

// CanonicalWebOriginFromURL returns a canonical representation of a web origin
// per RFC-6454 from a URL object. See https://www.ietf.org/rfc/rfc6454.txt
func CanonicalWebOriginFromURL(url *url.URL) string {
	return canonicalWebOrigin(url.Scheme, url.Hostname(), url.Port())
}

// CanonicalWebOriginFromRequestHost returns a canonical representation of a web
// origin per RFC-6454 from a Host header. See
// https://www.ietf.org/rfc/rfc6454.txt
func CanonicalWebOriginFromRequestHost(req *http.Request) string {
	scheme := "https"
	if req.TLS == nil {
		scheme = "http"
	}

	if forwardedProto := req.Header.Get("X-Forwarded-Proto"); forwardedProto != "" {
		scheme = forwardedProto
	}

	parts := strings.SplitN(req.Host, ":", 2)

	hostname := parts[0]

	var port string
	if len(parts) == 2 {
		port = parts[1]
	}

	return canonicalWebOrigin(scheme, hostname, port)
}

func canonicalWebOrigin(scheme, hostname, port string) string {
	if scheme == "" || hostname == "" {
		return UndefinedWebOrigin
	}

	scheme = strings.ToLower(scheme)
	hostname = strings.ToLower(hostname)

	if defaultPorts[scheme] == port || port == "" {
		return fmt.Sprintf("%s://%s", scheme, hostname)
	}

	return fmt.Sprintf("%s://%s:%s", scheme, hostname, port)
}
