package api

import (
	"fmt"
	"net/http"
	"sync"
	"time"

	"code.justin.tv/common/twitchhttp"
	"goji.io"
	"goji.io/pat"
	"golang.org/x/net/context"
)

type Server struct {
	*goji.Mux

	startTime  time.Time
	visits     int64
	visitsLock sync.Mutex
}

func NewServer() (*Server, error) {
	server := twitchhttp.NewServer()

	s := &Server{
		Mux:       server,
		startTime: time.Now(),
	}

	// Add your own endpoints here. Endpoint implementation should be defined as functions on Server.
	// For example: s.HandleFuncC(pat.Get("/my/path"), s.myEndpoint)
	// https://godoc.org/goji.io

	s.HandleFuncC(pat.Get("/"), s.hitCounter(s.EverythingIsFine))
	s.HandleFuncC(pat.Get("/health"), s.hitCounter(s.EverythingIsFine))
	s.HandleFuncC(pat.Get("/uptime"), s.hitCounter(s.Uptime))
	s.HandleFuncC(pat.Get("/visits"), s.hitCounter(s.Visits))
	s.HandleFuncC(pat.Get("/debug/running"), s.hitCounter(s.EverythingIsFine))
	return s, nil
}

func (s *Server) hitCounter(fn func(ctx context.Context, w http.ResponseWriter, r *http.Request)) func(context.Context, http.ResponseWriter, *http.Request) {
	return func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
		s.visitsLock.Lock()
		s.visits++
		s.visitsLock.Unlock()

		fn(ctx, w, r)
	}

}

func (s *Server) EverythingIsFine(ctx context.Context, w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("OK"))
}

func (s *Server) Uptime(ctx context.Context, w http.ResponseWriter, r *http.Request) {
	w.Write([]byte(time.Since(s.startTime).String()))
}

func (s *Server) Visits(ctx context.Context, w http.ResponseWriter, r *http.Request) {
	w.Write([]byte(fmt.Sprintf("%d", s.visits)))
}
