package main

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

	"code.hackerspace.pl/hscloud/go/mirko"
	"github.com/gobuffalo/packr"
	"github.com/q3k/statusz"
	"vbom.ml/util/sortorder"

	"code.hackerspace.pl/hscloud/go/svc/topo/graph"
	"code.hackerspace.pl/hscloud/go/svc/topo/state"

	ipb "code.hackerspace.pl/hscloud/go/proto/infra"
)

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

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

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>
`

const switchportsFragment = `
    <style type="text/css">
		.table td,th {
			background-color: #eee;
			padding: 0.2em 0.4em 0.2em 0.4em;
		}
		.table th {
			background-color: #c0c0c0;
		}
		.table {
			background-color: #fff;
			border-spacing: 0.2em;
			margin-left: auto;
			margin-right: auto;
		}
	</style>
	<div>
	<table class="table">
		<tr>
      		<th>Switch</th>
      		<th>Port</th>
			<th>Link State</th>
			<th>Port Mode</th>
			<th>MTU</th>
			<th>Sync Status</th>
		</tr>
		{{range .Ports }}
		{{ if .Managed }}
		<tr>
		{{ else }}
		<tr style="opacity: 0.5">
		{{ end}}
			<td style="text-align: right;">{{ .Switch }}</td>
			<td>{{ .Name }}</td>
			{{ if eq .State "DOWN" }}
			<td style="background-color: #ff3030;">{{ .State }}</td>
			{{ else }}
			<td>{{ .State }}</td>
			{{ end }}
			<td>{{ .Mode }}</td>
			<td>{{ .MTU }}</td>
			{{ if .Managed }}
			<td style="background-color: #30ff30;">OK</td>
			{{ else }}
			<td><i>Unmanaged</i></td>
			{{ end }}
		</tr>
		{{end}}
	</table>
	</div>
`

func (s *Service) Setup(m *mirko.Mirko) {
	assets := packr.NewBox("./assets")
	m.HTTPMux().Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(assets)))
	m.HTTPMux().HandleFunc("/debug/graphviz", s.httpHandleGraphviz)
	statusz.AddStatusPart("Switch Ports", switchportsFragment, s.statusHandleSwitchports)
	statusz.AddStatusPart("Topology", topologyFragment, func(ctx context.Context) interface{} {
		return nil
	})
}

func (s *Service) statusHandleSwitchports(ctx context.Context) interface{} {
	managedPorts := make(map[string]bool)
	s.gr.Mu.RLock()
	for _, sw := range s.gr.Switches {
		for _, port := range sw.Ports {
			managedPorts[sw.Name+"|"+port.Name] = true
		}
	}
	s.gr.Mu.RUnlock()

	s.stm.Mu.RLock()
	defer s.stm.Mu.RUnlock()

	res := struct {
		Ports []*struct {
			Switch  string
			Name    string
			State   string
			Mode    string
			Managed bool
			MTU     string
		}
	}{}
	for _, sw := range s.stm.Switches {
		for _, po := range sw.Ports {
			state := "INVALID"
			switch po.Proto.LinkState {
			case ipb.SwitchPort_LINKSTATE_DOWN:
				state = "DOWN"
			case ipb.SwitchPort_LINKSTATE_UP:
				state = "UP"
			}
			mode := "INVALID"
			switch po.Proto.PortMode {
			case ipb.SwitchPort_PORTMODE_SWITCHPORT_UNTAGGED:
				mode = fmt.Sprintf("UNTAGGED (%d)", po.Proto.VlanNative)
			case ipb.SwitchPort_PORTMODE_SWITCHPORT_TAGGED:
				mode = fmt.Sprintf("TAGGED (%v)", po.Proto.VlanTagged)
			case ipb.SwitchPort_PORTMODE_SWITCHPORT_GENERIC:
				mode = "GENERIC"
			case ipb.SwitchPort_PORTMODE_ROUTED:
				mode = "ROUTED"
			case ipb.SwitchPort_PORTMODE_MANGLED:
				mode = "MANGLED"
			}

			managed := managedPorts[sw.Name+"|"+po.Proto.Name]
			res.Ports = append(res.Ports, &struct {
				Switch  string
				Name    string
				State   string
				Mode    string
				Managed bool
				MTU     string
			}{
				Switch:  sw.Name,
				Name:    po.Proto.Name,
				State:   state,
				Mode:    mode,
				Managed: managed,
				MTU:     fmt.Sprintf("%d", po.Proto.Mtu),
			})
		}
	}

	return res
}

func (s *Service) httpHandleGraphviz(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")
}
