package models

import "strconv"

const (
	Iface2dot5G = "2.5gbase-t"
	Iface1G     = "1000base-t"
	Iface100M   = "100base-tx"
)

var speedAssociation map[string]int = map[string]int{
	"2.5gbase-t": 2500,
	"1000base-t": 1000,
	"100base-tx": 100,
}

type DeviceRole struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
	Slug string `json:"slug"`
}

type Device struct {
	ID   int        `json:"id"`
	Name string     `json:"name"`
	Role DeviceRole `json:"role"`
}

func (d Device) UniqueID() string {
	return "device-" + strconv.FormatInt(int64(d.ID), 10)
}

func (d Device) Element() Element {
	return Element{
		Data: ElementData{
			ID:    d.UniqueID(),
			Label: d.Name,
		},
		Classes: nil,
	}
}

type InterfaceType struct {
	Value string `json:"value"`
	Label string `json:"label"`
}

type Interface struct {
	ID         int           `json:"id"`
	Name       string        `json:"name"`
	Device     Device        `json:"device"`
	MacAddress string        `json:"mac_address"`
	Type       InterfaceType `json:"type"`
}

func (i Interface) MaxSpeed() int {
	speed, ok := speedAssociation[i.Type.Value]
	if !ok {
		return 0
	}
	return speed
}

type Object struct {
	Device    Device `json:"device"`
	Interface Interface
}

type CableTermination struct {
	ObjectID int    `json:"object_id"`
	Object   Object `json:"object"`
}

type Cable struct {
	ID            int                `json:"id"`
	ATerminations []CableTermination `json:"a_terminations"`
	BTerminations []CableTermination `json:"b_terminations"`
}

func (c Cable) UniqueID() string {
	return "link-" + strconv.FormatInt(int64(c.ID), 10)
}

func (c Cable) MaxSpeed() int {
	speedA := c.ATerminations[0].Object.Interface.MaxSpeed()
	speedB := c.BTerminations[0].Object.Interface.MaxSpeed()

	if speedA > speedB {
		return speedB
	}
	return speedA
}

func (c Cable) Element() Element {

	var linkClass string
	switch c.MaxSpeed() {
	case 2500:
		linkClass = "link-fast"
	case 1000:
		linkClass = "link-normal"
	case 100:
		linkClass = "link-slow"
	default:
		linkClass = "link-speed-unknown"
	}

	return Element{
		Data: ElementData{
			ID:     c.UniqueID(),
			Source: c.ATerminations[0].Object.Device.UniqueID(),
			Target: c.BTerminations[0].Object.Device.UniqueID(),
		},
		Classes: []string{"link", linkClass},
	}
}

type VM struct {
	ID     int    `json:"id"`
	Name   string `json:"name"`
	Device Device `json:"device"`
}

func (v VM) UniqueID() string {
	return "vm-" + strconv.FormatInt(int64(v.ID), 10)
}

func (v VM) Elements() []Element {
	return []Element{
		{
			Data: ElementData{
				ID:    v.UniqueID(),
				Label: v.Name,
			},
		},
		{
			Data: ElementData{
				ID:     "vm-cable" + strconv.FormatInt(int64(v.ID), 10),
				Source: v.UniqueID(),
				Target: v.Device.UniqueID(),
			},
			Classes: []string{"link", "link-virtual"},
		},
	}
}
