package ghttp

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"reflect"

	"github.com/golang/protobuf/proto"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/types"
)

//CombineHandler takes variadic list of handlers and produces one handler
//that calls each handler in order.
func CombineHandlers(handlers ...http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, req *http.Request) {
		for _, handler := range handlers {
			handler(w, req)
		}
	}
}

//VerifyRequest returns a handler that verifies that a request uses the specified method to connect to the specified path
//You may also pass in an optional rawQuery string which is tested against the request's `req.URL.RawQuery`
//
//For path, you may pass in a string, in which case strict equality will be applied
//Alternatively you can pass in a matcher (ContainSubstring("/foo") and MatchRegexp("/foo/[a-f0-9]+") for example)
func VerifyRequest(method string, path interface{}, rawQuery ...string) http.HandlerFunc {
	return func(w http.ResponseWriter, req *http.Request) {
		Ω(req.Method).Should(Equal(method), "Method mismatch")
		switch p := path.(type) {
		case types.GomegaMatcher:
			Ω(req.URL.Path).Should(p, "Path mismatch")
		default:
			Ω(req.URL.Path).Should(Equal(path), "Path mismatch")
		}
		if len(rawQuery) > 0 {
			values, err := url.ParseQuery(rawQuery[0])
			Ω(err).ShouldNot(HaveOccurred(), "Expected RawQuery is malformed")

			Ω(req.URL.Query()).Should(Equal(values), "RawQuery mismatch")
		}
	}
}

//VerifyContentType returns a handler that verifies that a request has a Content-Type header set to the
//specified value
func VerifyContentType(contentType string) http.HandlerFunc {
	return func(w http.ResponseWriter, req *http.Request) {
		Ω(req.Header.Get("Content-Type")).Should(Equal(contentType))
	}
}

//VerifyBasicAuth returns a handler that verifies the request contains a BasicAuth Authorization header
//matching the passed in username and password
func VerifyBasicAuth(username string, password string) http.HandlerFunc {
	return func(w http.ResponseWriter, req *http.Request) {
		auth := req.Header.Get("Authorization")
		Ω(auth).ShouldNot(Equal(""), "Authorization header must be specified")

		decoded, err := base64.StdEncoding.DecodeString(auth[6:])
		Ω(err).ShouldNot(HaveOccurred())

		Ω(string(decoded)).Should(Equal(fmt.Sprintf("%s:%s", username, password)), "Authorization mismatch")
	}
}

//VerifyHeader returns a handler that verifies the request contains the passed in headers.
//The passed in header keys are first canonicalized via http.CanonicalHeaderKey.
//
//The request must contain *all* the passed in headers, but it is allowed to have additional headers
//beyond the passed in set.
func VerifyHeader(header http.Header) http.HandlerFunc {
	return func(w http.ResponseWriter, req *http.Request) {
		for key, values := range header {
			key = http.CanonicalHeaderKey(key)
			Ω(req.Header[key]).Should(Equal(values), "Header mismatch for key: %s", key)
		}
	}
}

//VerifyHeaderKV returns a handler that verifies the request contains a header matching the passed in key and values
//(recall that a `http.Header` is a mapping from string (key) to []string (values))
//It is a convenience wrapper around `VerifyHeader` that allows you to avoid having to create an `http.Header` object.
func VerifyHeaderKV(key string, values ...string) http.HandlerFunc {
	return VerifyHeader(http.Header{key: values})
}

//VerifyJSON returns a handler that verifies that the body of the request is a valid JSON representation
//matching the passed in JSON string.  It does this using Gomega's MatchJSON method
//
//VerifyJSON also verifies that the request's content type is application/json
func VerifyJSON(expectedJSON string) http.HandlerFunc {
	return CombineHandlers(
		VerifyContentType("application/json"),
		func(w http.ResponseWriter, req *http.Request) {
			body, err := ioutil.ReadAll(req.Body)
			req.Body.Close()
			Ω(err).ShouldNot(HaveOccurred())
			Ω(body).Should(MatchJSON(expectedJSON), "JSON Mismatch")
		},
	)
}

//VerifyJSONRepresenting is similar to VerifyJSON.  Instead of taking a JSON string, however, it
//takes an arbitrary JSON-encodable object and verifies that the requests's body is a JSON representation
//that matches the object
func VerifyJSONRepresenting(object interface{}) http.HandlerFunc {
	data, err := json.Marshal(object)
	Ω(err).ShouldNot(HaveOccurred())
	return CombineHandlers(
		VerifyContentType("application/json"),
		VerifyJSON(string(data)),
	)
}

//VerifyForm returns a handler that verifies a request contains the specified form values.
//
//The request must contain *all* of the specified values, but it is allowed to have additional
//form values beyond the passed in set.
func VerifyForm(values url.Values) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		err := r.ParseForm()
		Ω(err).ShouldNot(HaveOccurred())
		for key, vals := range values {
			Ω(r.Form[key]).Should(Equal(vals), "Form mismatch for key: %s", key)
		}
	}
}

//VerifyFormKV returns a handler that verifies a request contains a form key with the specified values.
//
//It is a convenience wrapper around `VerifyForm` that lets you avoid having to create a `url.Values` object.
func VerifyFormKV(key string, values ...string) http.HandlerFunc {
	return VerifyForm(url.Values{key: values})
}

//VerifyProtoRepresenting returns a handler that verifies that the body of the request is a valid protobuf
//representation of the passed message.
//
//VerifyProtoRepresenting also verifies that the request's content type is application/x-protobuf
func VerifyProtoRepresenting(expected proto.Message) http.HandlerFunc {
	return CombineHandlers(
		VerifyContentType("application/x-protobuf"),
		func(w http.ResponseWriter, req *http.Request) {
			body, err := ioutil.ReadAll(req.Body)
			Ω(err).ShouldNot(HaveOccurred())
			req.Body.Close()

			expectedType := reflect.TypeOf(expected)
			actualValuePtr := reflect.New(expectedType.Elem())

			actual, ok := actualValuePtr.Interface().(proto.Message)
			Ω(ok).Should(BeTrue(), "Message value is not a proto.Message")

			err = proto.Unmarshal(body, actual)
			Ω(err).ShouldNot(HaveOccurred(), "Failed to unmarshal protobuf")

			Ω(actual).Should(Equal(expected), "ProtoBuf Mismatch")
		},
	)
}

func copyHeader(src http.Header, dst http.Header) {
	for key, value := range src {
		dst[key] = value
	}
}

/*
RespondWith returns a handler that responds to a request with the specified status code and body

Body may be a string or []byte

Also, RespondWith can be given an optional http.Header.  The headers defined therein will be added to the response headers.
*/
func RespondWith(statusCode int, body interface{}, optionalHeader ...http.Header) http.HandlerFunc {
	return func(w http.ResponseWriter, req *http.Request) {
		if len(optionalHeader) == 1 {
			copyHeader(optionalHeader[0], w.Header())
		}
		w.WriteHeader(statusCode)
		switch x := body.(type) {
		case string:
			w.Write([]byte(x))
		case []byte:
			w.Write(x)
		default:
			Ω(body).Should(BeNil(), "Invalid type for body.  Should be string or []byte.")
		}
	}
}

/*
RespondWithPtr returns a handler that responds to a request with the specified status code and body

Unlike RespondWith, you pass RepondWithPtr a pointer to the status code and body allowing different tests
to share the same setup but specify different status codes and bodies.

Also, RespondWithPtr can be given an optional http.Header.  The headers defined therein will be added to the response headers.
Since the http.Header can be mutated after the fact you don't need to pass in a pointer.
*/
func RespondWithPtr(statusCode *int, body interface{}, optionalHeader ...http.Header) http.HandlerFunc {
	return func(w http.ResponseWriter, req *http.Request) {
		if len(optionalHeader) == 1 {
			copyHeader(optionalHeader[0], w.Header())
		}
		w.WriteHeader(*statusCode)
		if body != nil {
			switch x := (body).(type) {
			case *string:
				w.Write([]byte(*x))
			case *[]byte:
				w.Write(*x)
			default:
				Ω(body).Should(BeNil(), "Invalid type for body.  Should be string or []byte.")
			}
		}
	}
}

/*
RespondWithJSONEncoded returns a handler that responds to a request with the specified status code and a body
containing the JSON-encoding of the passed in object

Also, RespondWithJSONEncoded can be given an optional http.Header.  The headers defined therein will be added to the response headers.
*/
func RespondWithJSONEncoded(statusCode int, object interface{}, optionalHeader ...http.Header) http.HandlerFunc {
	data, err := json.Marshal(object)
	Ω(err).ShouldNot(HaveOccurred())

	var headers http.Header
	if len(optionalHeader) == 1 {
		headers = optionalHeader[0]
	} else {
		headers = make(http.Header)
	}
	if _, found := headers["Content-Type"]; !found {
		headers["Content-Type"] = []string{"application/json"}
	}
	return RespondWith(statusCode, string(data), headers)
}

/*
RespondWithJSONEncodedPtr behaves like RespondWithJSONEncoded but takes a pointer
to a status code and object.

This allows different tests to share the same setup but specify different status codes and JSON-encoded
objects.

Also, RespondWithJSONEncodedPtr can be given an optional http.Header.  The headers defined therein will be added to the response headers.
Since the http.Header can be mutated after the fact you don't need to pass in a pointer.
*/
func RespondWithJSONEncodedPtr(statusCode *int, object interface{}, optionalHeader ...http.Header) http.HandlerFunc {
	return func(w http.ResponseWriter, req *http.Request) {
		data, err := json.Marshal(object)
		Ω(err).ShouldNot(HaveOccurred())
		var headers http.Header
		if len(optionalHeader) == 1 {
			headers = optionalHeader[0]
		} else {
			headers = make(http.Header)
		}
		if _, found := headers["Content-Type"]; !found {
			headers["Content-Type"] = []string{"application/json"}
		}
		copyHeader(headers, w.Header())
		w.WriteHeader(*statusCode)
		w.Write(data)
	}
}

//RespondWithProto returns a handler that responds to a request with the specified status code and a body
//containing the protobuf serialization of the provided message.
//
//Also, RespondWithProto can be given an optional http.Header.  The headers defined therein will be added to the response headers.
func RespondWithProto(statusCode int, message proto.Message, optionalHeader ...http.Header) http.HandlerFunc {
	return func(w http.ResponseWriter, req *http.Request) {
		data, err := proto.Marshal(message)
		Ω(err).ShouldNot(HaveOccurred())

		var headers http.Header
		if len(optionalHeader) == 1 {
			headers = optionalHeader[0]
		} else {
			headers = make(http.Header)
		}
		if _, found := headers["Content-Type"]; !found {
			headers["Content-Type"] = []string{"application/x-protobuf"}
		}
		copyHeader(headers, w.Header())

		w.WriteHeader(statusCode)
		w.Write(data)
	}
}
