package util

import (
	"encoding/json"
	"fmt"
	"log"
	"net"
	"net/http"
	"strconv"

	"code.justin.tv/common/chitin"
	"code.justin.tv/common/golibs/statsd"

	"github.com/stvp/rollbar"
	"golang.org/x/net/context"
)

// ErrorResponse represents a JSON error.
type ErrorResponse struct {
	Error         string
	VerboseError  string
	StatusCode    int
	StatusMessage string
}

// JSONError will format and return a JSON error. Msg is sent to the user and
// err is logged.
func JSONError(w http.ResponseWriter, statusCode int, msg string, err error) {
	log.Printf("error StatusCode=%d msg=%q err=%q", statusCode, msg, err)
	w.WriteHeader(statusCode)

	if rollbar.Token != "" {
		// Log to rollbar
		rollbar.Message(rollbar.ERR, fmt.Sprintf("%v: %v", msg, err))
	}

	if jsonErr := json.NewEncoder(w).Encode(&ErrorResponse{
		Error:         msg,
		StatusCode:    statusCode,
		StatusMessage: http.StatusText(statusCode),
		VerboseError:  err.Error(),
	}); jsonErr != nil {
		log.Printf("error msg=%q err=%q", "Error encoding JSON Error.", jsonErr)
	}
}

func MustSetupStatsd(host string, port int, prefix string) statsd.Stats {
	statsdAddr := net.JoinHostPort(host, strconv.Itoa(port))
	statsdClient, err := statsd.Dial("udp", statsdAddr, statsd.StatsConfig{
		Rate:   1.0,
		Prefix: prefix,
	})
	if err != nil {
		log.Fatalf("error creating statsd client: %v", err)
	}

	return statsdClient
}

// MustTraceContext is a small helper function that wraps getting a chitin
// context in a log.Fatal.
func MustTraceContext() context.Context {
	ctx, err := chitin.ExperimentalTraceContext(context.Background())
	if err != nil {
		log.Fatal(err)
	}

	return ctx
}
