package cache

import (
	"sync"

	"git.faercol.me/faercol/topology-map/internal/models"
)

func NewDataCache() *DataCache {
	return &DataCache{
		lock:       sync.Mutex{},
		devices:    make(map[int]*models.Device),
		interfaces: make(map[int]*models.Interface),
		cables:     make(map[int]*models.Cable),
		vms:        make(map[int]*models.VM),
	}
}

type DataCache struct {
	lock       sync.Mutex
	devices    map[int]*models.Device
	interfaces map[int]*models.Interface
	cables     map[int]*models.Cable
	vms        map[int]*models.VM
}

func (d *DataCache) AddDevice(device models.Device) {
	d.lock.Lock()
	defer d.lock.Unlock()
	d.devices[device.ID] = &device
}

func (d *DataCache) GetDevices() []*models.Device {
	d.lock.Lock()
	defer d.lock.Unlock()

	var res []*models.Device
	for _, dev := range d.devices {
		res = append(res, dev)
	}
	return res
}

func (d *DataCache) AddInterface(iface models.Interface) {
	d.lock.Lock()
	defer d.lock.Unlock()
	d.interfaces[iface.ID] = &iface
}

func (d *DataCache) GetInterfaces() []*models.Interface {
	d.lock.Lock()
	defer d.lock.Unlock()

	var res []*models.Interface
	for _, iface := range d.interfaces {
		res = append(res, iface)
	}
	return res
}

func (d *DataCache) AddCable(cable models.Cable) {
	d.lock.Lock()
	defer d.lock.Unlock()
	d.cables[cable.ID] = &cable
}

func (d *DataCache) GetCables() []*models.Cable {
	d.lock.Lock()
	defer d.lock.Unlock()

	var res []*models.Cable
	for _, cable := range d.cables {
		res = append(res, cable)
	}
	return res
}

func (d *DataCache) AddVM(vm models.VM) {
	d.lock.Lock()
	defer d.lock.Unlock()
	d.vms[vm.ID] = &vm
}

func (d *DataCache) GetVMs() []*models.VM {
	d.lock.Lock()
	defer d.lock.Unlock()

	var res []*models.VM
	for _, vm := range d.vms {
		res = append(res, vm)
	}
	return res
}

func (d *DataCache) ReconcileData() {
	d.lock.Lock()
	defer d.lock.Unlock()

	for id, cable := range d.cables {
		ifaceA, ok := d.interfaces[cable.ATerminations[0].ObjectID]
		if !ok {
			continue
		}
		cable.ATerminations[0].Object.Interface = *ifaceA

		ifaceB, ok := d.interfaces[cable.BTerminations[0].ObjectID]
		if !ok {
			continue
		}
		cable.BTerminations[0].Object.Interface = *ifaceB

		d.cables[id] = cable

	}
}
