// Copyright 2024 WIT.COM Inc Licensed GPL 3.0

package main

import (
	"fmt"
	"os"

	"go.wit.com/log"
	"libvirt.org/go/libvirtxml"
)

func makeStandardXml(d *DropletT) *libvirtxml.Domain {
	log.Info("create new xml file for:", d.pb.Hostname)
	domcfg := &libvirtxml.Domain{}

	addDefaults(domcfg, "standard.x86")
	addDefaults(domcfg, "memory")
	addDefaults(domcfg, "network")
	addDefaults(domcfg, "spice")
	addDefaults(domcfg, "qcow")
	addDefaults(domcfg, d.pb.Hostname)

	return domcfg
}

func writeoutXml(domcfg *libvirtxml.Domain, filename string) bool {
	xmldoc, err := domcfg.Marshal()

	if err != nil {
		fmt.Println("can't make xml file error:\n", err)
		return false
	}

	outfile := "/tmp/" + filename + ".xml"
	regfile, _ := os.OpenFile(outfile, os.O_RDWR|os.O_CREATE, 0666)
	fmt.Fprintln(regfile, xmldoc)

	log.Info("File is in", outfile)
	regfile.Close()
	return true
}

func setDiskFilename(domcfg *libvirtxml.Domain, filename string) {
	for i, x := range domcfg.Devices.Disks {
		// Create a new DomainDiskSourceFile struct
		newSource := &libvirtxml.DomainDiskSourceFile{
			File: filename, // Set the file name here
		}

		// Assign it to the disk's source
		domcfg.Devices.Disks[i].Source.File = newSource

		// fmt.Printf("Disk Source %s\n", name)
		fmt.Printf("Disk Device %s\n", x.Source.File)
	}
}

func addDefaults(d *libvirtxml.Domain, filename string) {
	fullname := "resources/xml/" + filename + ".xml"
	pfile, err := resources.ReadFile(fullname)
	if err != nil {
		log.Println("ERROR:", err)
		return
	}

	err = d.Unmarshal(string(pfile))
	if err != nil {
		log.Info("Marshal failed on file", filename)
		return
	}
}

func readXml(filename string) (*libvirtxml.Domain, error) {
	log.Info("parse xml file:", filename)

	pfile, err := os.ReadFile(filename)
	if err != nil {
		log.Println("ERROR:", err)
		return nil, err
	}

	domcfg := &libvirtxml.Domain{}

	err = domcfg.Unmarshal(string(pfile))
	if err != nil {
		log.Info("Marshal failed on file", filename, err)
		return nil, ErrorParseXML
	}
	return domcfg, nil
}

func (d *DropletT) mergeXml(filename string) error {
	log.Info("parse xml file:", filename)

	pfile, err := os.ReadFile(filename)
	if err != nil {
		log.Println("ERROR:", err)
		return ErrorNoFile
	}

	err = d.xml.Unmarshal(string(pfile))
	if err != nil {
		log.Info("Marshal failed on file", filename)
		return ErrorParseXML
	}
	return nil
}

func setSimpleDisk(domcfg *libvirtxml.Domain, filename string) {
	// Clear out the existing disks (if any)
	domcfg.Devices.Disks = nil

	// Define a new disk with "mynew.qcow2"
	newDisk := libvirtxml.DomainDisk{
		Device: "disk",
		Driver: &libvirtxml.DomainDiskDriver{
			Name: "qemu",
			Type: "qcow2",
		},
		Source: &libvirtxml.DomainDiskSource{
			File: &libvirtxml.DomainDiskSourceFile{
				File: filename,
			},
		},
		Target: &libvirtxml.DomainDiskTarget{
			Dev: "vda",
			Bus: "virtio",
		},
	}

	// Add the new disk to the domain configuration
	domcfg.Devices.Disks = append(domcfg.Devices.Disks, newDisk)
}

func getMacs(domcfg *libvirtxml.Domain) []string {
	var macs []string
	// Iterate over the network interfaces and print the MAC addresses
	for _, iface := range domcfg.Devices.Interfaces {
		if iface.MAC != nil {
			// iface.MAC.Address = "aa:bb:aa:bb:aa:ff"
			fmt.Printf("MAC Address: %+v\n", iface.MAC)
			// fmt.Printf("Interface: %s, MAC Address: %s\n", iface.Target.Dev, iface.MAC.Address)
			macs = append(macs, iface.MAC.Address)
		} else {
			fmt.Printf("Interface: %s, MAC Address: not available\n", iface.Target.Dev)
		}
	}
	return macs
}

// removes all the ethernet interfaces
func clearEthernet(domcfg *libvirtxml.Domain) {
	// Clear out the existing disks (if any)
	domcfg.Devices.Interfaces = nil
}

// add a new ethernet interface with mac assigned to bridge name
func addEthernet(domcfg *libvirtxml.Domain, mac string, brname string) {
	// Define a new disk with "mynew.qcow2"
	newNet := libvirtxml.DomainInterface{
		MAC: &libvirtxml.DomainInterfaceMAC{
			Address: mac,
		},
		Target: &libvirtxml.DomainInterfaceTarget{
			Dev: brname,
		},
	}

	// Add the new disk to the domain configuration
	domcfg.Devices.Interfaces = append(domcfg.Devices.Interfaces, newNet)
}

func setRandomMacs(domcfg *libvirtxml.Domain) {
	for i, x := range domcfg.Devices.Interfaces {
		// Create a new DomainDiskInterfaces struct
		newMac := &libvirtxml.DomainInterfaceMAC{
			Address: "aa:bb:cc:dd:ee:ff", // make sure this is unique
		}

		// Assign it to the disk's source
		domcfg.Devices.Interfaces[i].MAC = newMac

		// fmt.Printf("Disk Source %s\n", name)
		// fmt.Printf("mac addr %+v\n", x.MAC)
		fmt.Printf("mac addr %s\n", x.MAC.Address)
	}
}