package graph

import (
	"context"
	"fmt"
	"sync"

	"github.com/digitalocean/go-netbox/netbox/client"
	"github.com/digitalocean/go-netbox/netbox/client/dcim"
	"github.com/digitalocean/go-netbox/netbox/models"
	"github.com/golang/glog"

	pb "code.hackerspace.pl/hscloud/dc/topo/proto"
)

type MachinePort struct {
	Machine  *Machine
	OtherEnd *SwitchPort
	Name     string
}

type SwitchPort struct {
	Switch   *Switch
	OtherEnd *MachinePort
	Name     string
}

type Machine struct {
	Name     string
	Complete bool

	Ports map[string]*MachinePort
}

type Switch struct {
	Name     string
	Complete bool

	Ports map[string]*SwitchPort
}

type Graph struct {
	Switches map[string]*Switch
	Machines map[string]*Machine
	Mu       sync.RWMutex
}

func New() *Graph {
	return &Graph{
		Switches: make(map[string]*Switch),
		Machines: make(map[string]*Machine),
	}
}

func (g *Graph) RemoveMachine(name string) {
	glog.Infof("Removed machine %q", name)
}

func (g *Graph) RemoveSwitch(name string) {
	glog.Infof("Removed switch %q", name)
}

func (g *Graph) LoadConfig(conf *pb.Config) error {
	loadedMachines := make(map[string]bool)
	loadedSwitches := make(map[string]bool)

	// Add new machines and switches.
	for _, machinepb := range conf.Machine {
		if machinepb.Name == "" {
			return fmt.Errorf("empty machine name")
		}
		if loadedMachines[machinepb.Name] {
			return fmt.Errorf("duplicate machine name: %v", machinepb.Name)
		}
		machine, ok := g.Machines[machinepb.Name]
		if !ok {
			machine = &Machine{
				Name:  machinepb.Name,
				Ports: make(map[string]*MachinePort),
			}
			for _, portpb := range machinepb.ManagedPort {
				machine.Ports[portpb.Name] = &MachinePort{
					Name:    portpb.Name,
					Machine: machine,
				}
			}
			g.Machines[machinepb.Name] = machine
			glog.Infof("Added machine %q with %d managed ports", machine.Name, len(machine.Ports))
		}
		machine.Complete = false
		loadedMachines[machinepb.Name] = true
	}
	for _, switchpb := range conf.Switch {
		if switchpb.Name == "" {
			return fmt.Errorf("empty switch name")
		}
		if loadedSwitches[switchpb.Name] {
			return fmt.Errorf("duplicate switch name: %v", switchpb.Name)
		}
		if loadedMachines[switchpb.Name] {
			return fmt.Errorf("switch name collides with machine name: %v", switchpb.Name)
		}
		sw, ok := g.Switches[switchpb.Name]
		if !ok {
			sw = &Switch{
				Name:  switchpb.Name,
				Ports: make(map[string]*SwitchPort),
			}
			for _, portpb := range switchpb.ManagedPort {
				sw.Ports[portpb.Name] = &SwitchPort{
					Name:   portpb.Name,
					Switch: sw,
				}
			}
			g.Switches[switchpb.Name] = sw
			glog.Infof("Added switch %q with %d managed ports", sw.Name, len(sw.Ports))
		}
		sw.Complete = false
		loadedSwitches[switchpb.Name] = true
	}

	// Remove old machines and switches.
	removeMachines := make(map[string]bool)
	removeSwitches := make(map[string]bool)
	for name, _ := range g.Switches {
		if !loadedSwitches[name] {
			removeSwitches[name] = true
		}
	}
	for name, _ := range g.Machines {
		if !loadedMachines[name] {
			removeMachines[name] = true
		}
	}
	for name, _ := range removeMachines {
		g.RemoveMachine(name)
	}
	for name, _ := range removeSwitches {
		g.RemoveSwitch(name)
	}
	return nil

}

func (g *Graph) FeedFromNetbox(ctx context.Context, nb *client.NetBoxAPI) error {
	// Clear all connections first, because it's easier that way.
	for _, machine := range g.Machines {
		for _, port := range machine.Ports {
			port.OtherEnd = nil
		}
	}
	for _, sw := range g.Switches {
		for _, port := range sw.Ports {
			port.OtherEnd = nil
		}
	}

	// Load new connections.
	// Iterating over just machines should be fine if all connections are
	// guaranteed to be between machines and switches (which is the model for
	// now).
	for _, machine := range g.Machines {
		req := &dcim.DcimInterfaceConnectionsListParams{
			Device:  &machine.Name,
			Context: ctx,
		}
		res, err := nb.Dcim.DcimInterfaceConnectionsList(req, nil)
		if err != nil {
			return fmt.Errorf("while querying information about %q: %v", machine.Name, err)
		}
		for _, connection := range res.Payload.Results {
			ia := connection.Interfacea
			ib := connection.Interfaceb
			if ia == nil || ib == nil {
				continue
			}

			// Find which way this thing actually connects.
			var thisSide, otherSide *models.NestedInterface
			if ia.Device.Name != nil && *ia.Device.Name == machine.Name {
				thisSide = ia
				otherSide = ib
			} else if ib.Device.Name != nil && *ib.Device.Name == machine.Name {
				thisSide = ib
				otherSide = ia
			} else {
				glog.Warning("Netbox connectivity for %q reported a link without it involced..?", machine.Name)
				continue
			}

			thisPort, ok := machine.Ports[*thisSide.Name]
			if !ok {
				continue
			}
			sw, ok := g.Switches[*otherSide.Device.Name]
			if !ok {
				glog.Warningf("Machine %q port %q is managed but connected to unknown device %q", machine.Name, thisPort.Name, *otherSide.Device.Name)
				continue
			}
			otherPort, ok := sw.Ports[*otherSide.Name]
			if !ok {
				glog.Warningf("Machine %q port %q is managed but connected to unmanaged port %q on %q", machine.Name, thisPort.Name, otherSide.Name, sw.Name)
				continue
			}

			// Connect the two together!
			thisPort.OtherEnd = otherPort
			otherPort.OtherEnd = thisPort
			glog.Infof("Connected: %s/%s <-> %s/%s", machine.Name, thisPort.Name, sw.Name, otherPort.Name)
		}
	}
	return nil
}
