package tmobtokengen

import (
	"crypto/sha256"
	"encoding/base64"
	"strings"
)

type EhtsKey string

const (
	Authorization EhtsKey = "Authorization"
	URI           EhtsKey = "uri"
	HTTPMethod    EhtsKey = "http-method"
	ContentType   EhtsKey = "Content-Type"
	B2BClient     EhtsKey = "B2b-client" // No idea what this is for
	Body          EhtsKey = "body"
)

// ehtsKeyList order is important for serialization.
var ehtsKeyList = []EhtsKey{Authorization, URI, HTTPMethod, Body, ContentType, B2BClient}

func ehtsToString(ehts map[EhtsKey]string) (ks string, vs string) {
	kb, vb := new(strings.Builder), new(strings.Builder)
	for _, k := range ehtsKeyList {
		v, ok := ehts[k]
		if !ok {
			continue
		}

		if kb.Len() > 0 {
			kb.WriteRune(';')
		}

		kb.WriteString(string(k))
		vb.WriteString(v)
	}

	return kb.String(), vb.String()
}

func b64EncodeEHTS(ehts []byte) []byte {
	sum := sha256.Sum256(ehts)
	encoded := make([]byte, base64.URLEncoding.EncodedLen(len(sum)))
	base64.URLEncoding.Encode(encoded, sum[:])

	// It appears to be that T-Mob removes the padding.
	i := len(encoded) - 1
	for ; i > 0; i-- {
		if i != '=' {
			break
		}
	}

	return encoded[:i]
}

// EHTSMap is a map of EHTS keys and values.
// Set[X] methods are used to set values in the map,
// Yet if the value for the given setter is empty, it won't set anything.
// Thus remember to set explicitly the value to empty string if there is need.
type EHTSMap map[EhtsKey]string

func (m EHTSMap) Copy() EHTSMap {
	c := make(EHTSMap)
	for k, v := range m {
		c[k] = v
	}

	return c
}
func (m EHTSMap) SetContentType(contentType string) EHTSMap {
	if len(contentType) > 0 {
		m[ContentType] = contentType
	}

	return m
}

func (m EHTSMap) SetAuthorization(authorization string) EHTSMap {
	if len(authorization) > 0 {
		m[Authorization] = authorization
	}

	return m
}

func (m EHTSMap) SetB2BClient(b2bClient string) EHTSMap {
	if len(b2bClient) > 0 {
		m[B2BClient] = b2bClient
	}

	return m
}

func (m EHTSMap) SetURI(uri string) EHTSMap {
	if len(uri) > 0 {
		m[URI] = uri
	}

	return m
}

func (m EHTSMap) SetBody(body string) EHTSMap {
	if len(body) > 0 {
		m[Body] = body
	}

	return m
}

func (m EHTSMap) SetHTTPMethod(httpMethod string) EHTSMap {
	if len(httpMethod) > 0 {
		m[HTTPMethod] = httpMethod
	}

	return m
}
