package hdx

import (
	"encoding/json"
	"io"
	"log"
	"net"
	"net/http"
	"time"
)

var Version string = "dev"
var start time.Time

type failure struct {
	Success bool   `json:"success"`
	Error   string `json:"error"`
}

func NewFailure(msg string) *failure {
	return &failure{
		Success: false,
		Error:   msg,
	}
}

type Server struct {
	db *DB
}

type visit struct {
	IP    net.IP `json:"ip"`
	Count int    `json:"count"`
}

func init() {
	log.SetFlags(log.Ltime)
	start = time.Now()
}

func NewServer(sm *http.ServeMux, dbhost, dbname, dbuser, static string) (*Server, error) {
	db, err := NewDB(dbhost, dbname, dbuser)
	if err != nil {
		return nil, err
	}
	db.db.SetMaxOpenConns(32)

	server := &Server{
		db: db,
	}
	addRoutes(sm, server, static)
	return server, nil
}

func (s *Server) serverInfo(w http.ResponseWriter, r *http.Request) {
	output := struct {
		Version string `json:"version"`
		Start   string `json:"start"`
		Uptime  string `json:"uptime"`
	}{
		Version: Version,
		Start:   start.Format("2006-01-02 15:04:05"),
		Uptime:  time.Since(start).String(),
	}
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(output)
}

func (s *Server) health(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
	w.Header().Set("Content-Type", "application/json")
	io.WriteString(w, `{"alive": true}`)
}

func (s *Server) visit(w http.ResponseWriter, req *http.Request) {
	switch req.Method {
	default:
		b, _ := json.Marshal(NewFailure("Allowed methods: GET"))
		http.Error(w, string(b), http.StatusBadRequest)
		return
	case "GET":
		//ip := net.ParseIP(getIP(req))
		ip := getIP(req)
		if ip == "" {
			log.Printf("did not receive valid ip")
			b, _ := json.Marshal(NewFailure("did not receive valid ip"))
			http.Error(w, string(b), http.StatusBadRequest)
			return
		}
		_, err := s.db.db.Exec(
			`INSERT INTO ips (ip) VALUES ($1)`,
			string(ip),
		)
		if err != nil {
			log.Printf("%+v", err)
			b, _ := json.Marshal(NewFailure(err.Error()))
			http.Error(w, string(b), http.StatusBadRequest)
			return
		}
		c, err := s.db.getcount(ip)
		if err != nil {
			log.Printf("%+v", err)
			b, _ := json.Marshal(NewFailure(err.Error()))
			http.Error(w, string(b), http.StatusBadRequest)
			return
		}
		v := visit{IP: net.ParseIP(ip), Count: c}
		json.NewEncoder(w).Encode(v)
	}
}
