package main

import (
	"html/template"
	"net/http"
	"os"
	"path"
	"strings"
	"time"
)

var epoch = time.Unix(0, 0).Format(time.RFC1123)

var noCacheHeaders = map[string]string{
	"Expires":         epoch,
	"Cache-Control":   "no-cache, private, max-age=0",
	"Pragma":          "no-cache",
	"X-Accel-Expires": "0",
}

var etagHeaders = []string{
	"ETag",
	"If-Modified-Since",
	"If-Match",
	"If-None-Match",
	"If-Range",
	"If-Unmodified-Since",
}

func serveTemplate(w http.ResponseWriter, r *http.Request) {
	logit("Called URL: " + r.URL.Path)
	// wennn kein File angegeben ist: index.html
	if r.URL.Path == "/" {
		r.URL.Path = "/index.html"
	}
	lp := path.Join("templates", "layout.html")
	fp := path.Join("snippets", r.URL.Path)

	// Return a 404 if the template doesn't exist
	_, err := os.Stat(fp)
	if err != nil {
		if os.IsNotExist(err) {
			logit("URL not found: " + fp)
			fp = path.Join("snippets", "404.html")
		}
	}

	tmpl, err := template.ParseFiles(lp, fp)
	if err != nil {
		// Log the detailed error
		logit(err.Error())
		// Return a generic "Internal Server Error" message
		http.Error(w, http.StatusText(500), 500)
		return
	}

	var userName = getUserName(r)

	t := time.Now()
	var datetimestring = t.Format("20060102150405")
	var trackers = getMyDevs(userName)
	var last_metrics []OneMetric

	query_values := r.URL.Query()

	if r.URL.Path == "/tracker.html" {
		// wir holen noch die letzten Metriken
		for _, v := range trackers {
			deveui := v
			readonly := false
			if strings.HasPrefix(deveui, "@") {
				deveui = deveui[1:]
				readonly = true
			}
			last_metric := getLastMetrics(deveui)
			last_metric.Readonly = readonly
			last_metrics = append(last_metrics, last_metric)
		}
	}

	data := struct {
		UserName       string
		DateTimeString string
		Tracker        []string
		LastMetrics    []OneMetric
		QueryValues    map[string][]string
	}{
		userName,
		datetimestring,
		trackers,
		last_metrics,
		query_values,
	}

	// because of caching, we need to set the Last-Modified header
	w.Header().Set("Last-Modified", time.Now().Format(http.TimeFormat))

	// Delete any ETag headers that may have been set
	for _, v := range etagHeaders {
		if r.Header.Get(v) != "" {
			r.Header.Del(v)
		}
	}

	// Set our NoCache headers
	for k, v := range noCacheHeaders {
		w.Header().Set(k, v)
	}

	if err := tmpl.ExecuteTemplate(w, "layout", &data); err != nil {
		logit(err.Error())
		http.Error(w, http.StatusText(500), 500)
	}
}

func main() {
	initDB()
	defer closeDB()
	fs := http.FileServer(http.Dir("static"))
	http.Handle("/static/", http.StripPrefix("/static/", fs))
	http.Handle("/favicon.ico", fs)
	http.HandleFunc("/", serveTemplate)

	http.HandleFunc("/login", loginHandler)
	http.HandleFunc("/reset_password", resetPasswordHandler)
	http.HandleFunc("/set_password", setPasswordHandler)
	http.HandleFunc("/logout", logoutHandler)
	http.HandleFunc("/confirm", confirmHandler)
	http.HandleFunc("/metrics", metricsHandler)
	http.HandleFunc("/abocost", abocostHandler)
	http.HandleFunc("/downloadmetrics", downloadmetricsHandler)
	http.HandleFunc("/order", orderHandler)
	http.HandleFunc("/save_tracker_settings", save_tracker_settingsHandler)
	http.HandleFunc("/save_tracker_greenzone", save_tracker_greenzoneHandler)
	http.HandleFunc("/getstripepaymentintent", getstripepaymentintentHandler)
	http.HandleFunc("/stripewebhook", stripeWebhookHandler)
	http.HandleFunc("/checknodes", checkNodesHandler)

	logit("Starting Web Application...")
	http.ListenAndServe(":4000", nil)
	logit("Terminating Web Application...")
}
