package main

import (
	"context"
	"fmt"
	"net/http"
	"sort"
	"strings"

	"github.com/gobuffalo/packr"
	"github.com/golang/glog"
	"github.com/q3k/statusz"
	"vbom.ml/util/sortorder"

	"code.hackerspace.pl/q3k/topo/graph"
	"code.hackerspace.pl/q3k/topo/state"
)

type ServiceConfig struct {
	DebugListen string
}

type Service struct {
	gr     *graph.Graph
	stm    *state.StateManager
	config ServiceConfig
}

func NewService(gr *graph.Graph, stm *state.StateManager, c ServiceConfig) *Service {
	return &Service{
		gr:     gr,
		stm:    stm,
		config: c,
	}
}

type TopologyStatus struct {
}

const topologyFragment = `
  <script src="/assets/viz.js"></script>
  <script>

    var viz = new Viz({ workerURL: '/assets/full.render.js' });
	var xmlhttp = new XMLHttpRequest();
	xmlhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        var dot = this.responseText;
        viz.renderSVGElement(dot)
        .then(function(element) {
          document.getElementById("graph").appendChild(element);
        });
      }
    };
    xmlhttp.open('GET', '/debug/graphviz');
    xmlhttp.send();

  </script>
  <div id="graph" style="text-align: center;"></div>
`

func (s *Service) Run() {
	assets := packr.NewBox("./assets")
	http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(assets)))

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, "/debug/status", http.StatusSeeOther)
	})

	http.HandleFunc("/debug/graphviz", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "graph G {\n")
		fmt.Fprintf(w, "  ranksep = 2\n")
		fmt.Fprintf(w, "  splines = polyline\n")
		fmt.Fprintf(w, "  rankdir = LR\n")
		for _, machine := range s.gr.Machines {
			portNames := []string{}
			for _, port := range machine.Ports {
				name := fmt.Sprintf("<%s> %s", port.Name, port.Name)
				portNames = append(portNames, name)
			}
			ports := strings.Join(portNames, "|")
			fmt.Fprintf(w, "  %s [shape=record label=\"{ %s | { %s }}\"]\n", machine.Name, machine.Name, ports)
		}
		for _, sw := range s.gr.Switches {
			portNames := []string{}
			portsOrdered := []*graph.SwitchPort{}
			for _, port := range sw.Ports {
				portsOrdered = append(portsOrdered, port)
			}
			sort.Slice(portsOrdered, func(i, j int) bool {
				return sortorder.NaturalLess(portsOrdered[i].Name, portsOrdered[j].Name)
			})
			for _, port := range portsOrdered {
				name := fmt.Sprintf("<%s> %s", port.Name, port.Name)
				portNames = append(portNames, name)
			}
			ports := strings.Join(portNames, "|")
			fmt.Fprintf(w, "  %s [shape=record label=\"{{ %s } | %s}\"]\n", sw.Name, ports, sw.Name)
		}
		for _, machine := range s.gr.Machines {
			for _, port := range machine.Ports {
				if port.OtherEnd == nil {
					continue
				}
				fmt.Fprintf(w, "  %s:%q:e -- %s:%q:w\n", machine.Name, port.Name, port.OtherEnd.Switch.Name, port.OtherEnd.Name)
			}
		}
		fmt.Fprintf(w, "}\n")
	})

	statusz.AddStatusPart("Topology", topologyFragment, func(ctx context.Context) interface{} {
		return &TopologyStatus{}
	})
	glog.Infof("Debug listening on %s....", s.config.DebugListen)
	http.ListenAndServe(s.config.DebugListen, nil)
}
