package main

import (
	"encoding/json"
	"fmt"
	"html/template"
	"net/http"

	"git.faercol.me/faercol/topology-map/internal/cache"
	"git.faercol.me/faercol/topology-map/internal/models"
	"git.faercol.me/faercol/topology-map/internal/netbox"
)

const apiKey = "4e75b8927940adc29e2e1eac042bf92bcddd57fe"
const netboxBaseURL = "https://netbox.internal.faercol.me/api/"

func main() {

	fmt.Println("Initializing data")
	dataCache := cache.NewDataCache()
	netboxClt := netbox.NewClient(netboxBaseURL, apiKey)

	fmt.Println("Getting devices")
	devices, err := netboxClt.GetDevices()
	if err != nil {
		panic(err)
	}
	for _, d := range devices {
		dataCache.AddDevice(d)
	}

	fmt.Println("Getting VMs")
	vms, err := netboxClt.GetVMs()
	if err != nil {
		panic(err)
	}
	for _, v := range vms {
		dataCache.AddVM(v)
	}

	fmt.Println("Getting cables")
	cables, err := netboxClt.GetCables()
	if err != nil {
		panic(err)
	}
	for _, c := range cables {
		dataCache.AddCable(c)
	}

	fmt.Println("Getting interfaces")
	interfaces, err := netboxClt.GetInterfaces()
	if err != nil {
		panic(err)
	}
	for _, i := range interfaces {
		dataCache.AddInterface(i)
	}

	fmt.Println("Reconciling data")
	dataCache.ReconcileData()
	fmt.Println("Done")

	srv := http.NewServeMux()

	srv.HandleFunc("/static/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Println("Serving static file")
		fs := http.FileServer(http.Dir("./static"))
		http.StripPrefix("/static", fs).ServeHTTP(w, r)
	})
	srv.HandleFunc("/api/data", func(w http.ResponseWriter, r *http.Request) {
		fmt.Println("Serving API route")

		resp := []models.Element{}
		for _, d := range dataCache.GetDevices() {
			resp = append(resp, d.Element())
		}
		for _, c := range dataCache.GetCables() {
			resp = append(resp, c.Element())
		}
		for _, v := range dataCache.GetVMs() {
			resp = append(resp, v.Elements()...)
		}

		respBody, err := json.Marshal(resp)
		if err != nil {
			fmt.Printf("Failed to serialize data: %s\n", err)
			w.WriteHeader(500)
			return
		}

		w.Header().Add("Content-Type", "application/json")
		w.Write(respBody)
	})
	srv.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Println("Serving main root")
		tpl, err := template.New("index.html").ParseFiles("templates/index.html")
		if err != nil {
			fmt.Printf("Failed to read template: %s\n", err)
			w.WriteHeader(500)
			return
		}

		if err := tpl.Execute(w, nil); err != nil {
			fmt.Printf("Failed to execute template: %s\n", err)
			w.WriteHeader(500)
			return
		}
	})

	if err := http.ListenAndServe("0.0.0.0:5000", srv); err != nil {
		panic(err)
	}
}
