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.NetBox) 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.PeerInterface
			if ia.Device.Name == machine.Name {
				thisSide = ia
				otherSide = ib
			} else if 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
}
