package twitchhttp

import (
	"log"
	"net/http"
	// importing twitchhttp implies intent to host pprof metrics, so we automatically enable it.
	_ "net/http/pprof"
	"time"

	"code.justin.tv/common/chitin"
	"code.justin.tv/common/config"
	"code.justin.tv/common/gometrics"

	"goji.io"
	"goji.io/pat"
	"golang.org/x/net/context"
)

// Server allows simple definition of an HTTP service which meets Twitch requirements for production readiness.
func init() {
	config.Register(map[string]string{
		"bind-address":       ":8000",
		"debug-bind-address": ":6000",
	})
}

// NewServer allocates and returns a Server. The /debug/running endpoint is registered for load balancer health checks.
func NewServer() *goji.Mux {
	router := goji.NewMux()
	router.UseC(RollbarMiddleware)
	router.HandleFuncC(pat.Get("/debug/running"), healthcheck)
	return router
}

// ListenAndServe starts the application server, as well as a debug server for pprof debugging. Go runtime metrics begin emitting to statsd.
func ListenAndServe(h goji.Handler) error {
	ctx, err := chitin.ExperimentalTraceContext(context.Background())
	if err != nil {
		return err
	}

	go func() {
		log.Printf("debug listening on %v", config.Resolve("debug-bind-address"))
		log.Print(http.ListenAndServe(config.Resolve("debug-bind-address"), nil))
	}()

	gometrics.Monitor(config.Statsd(), time.Second*5)

	log.Printf("application listening on %v", config.Resolve("bind-address"))
	return http.ListenAndServe(config.Resolve("bind-address"), chitin.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ctx := chitin.Context(w, r)
		h.ServeHTTPC(ctx, w, r)
	}), chitin.SetBaseContext(ctx)))
}

// RollbarMiddleware intercepts panics and sends them to rollbar before re-panicing
func RollbarMiddleware(h goji.Handler) goji.Handler {
	return goji.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
		defer func() {
			if p := recover(); p != nil {
				if config.RollbarErrorLogger() != nil {
					config.RollbarErrorLogger().RequestPanic(r, p)
				}
				panic(p)
			}
		}()

		h.ServeHTTPC(ctx, w, r)
	})
}

func healthcheck(ctx context.Context, w http.ResponseWriter, r *http.Request) {
	w.Header().Add("Cache-Control", "no-cache, no-store, must-revalidate")
	_, err := w.Write([]byte("OK"))
	if err != nil {
		log.Printf("health check failed to respond: %v", err)
	}
}
