package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"

	"gopkg.in/yaml.v3"
)

type NetDevConfig map[string]interface{}
type ContainerConfig map[string]interface{}
type VolumeConfig map[string]interface{}

type YamlTopology struct {
	Devices    []NetDevConfig    `yaml:"devices"`
	Containers []ContainerConfig `yaml:"containers"`
	Volumes    []VolumeConfig    `yaml:"volumes"`
}

func AddAddress(device, address, ns string) error {
	c := []string{"ip", "addr", "add", address, "dev", device}
	cmd := appendNetns(c, ns)
	err := cmd.Run()
	if err != nil {
		return fmt.Errorf("failed to set ip address for %s: %v", device, err)
	}
	return nil
}

func convertToNetConfig(t *YamlTopology) (*NetTopology, error) {
	var topology NetTopology
	for _, dev := range t.Devices {
		topology = append(topology, NewNetConfig(dev))
	}
	return &topology, nil
}

func loadTopoFile(topoName string) (*NetTopology, error) {
	var yamlTopo YamlTopology

	data, err := ioutil.ReadFile(topoName)
	if err != nil {
		return nil, fmt.Errorf("read error: %v", err)
	}

	err = yaml.Unmarshal(data, &yamlTopo)
	if err != nil {
		return nil, fmt.Errorf("error parsing topology data: %v", err)
	}

	return convertToNetConfig(&yamlTopo)
}

func LoadTopology(path, topoName string) (*NetTopology, error) {
	dir, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer dir.Close()

	files, err := dir.Readdir(0)
	if err != nil {
		return nil, err
	}

	for i := range files {
		file := files[i]
		fileName := file.Name()

		// cut off file extension
		f := strings.Split(fileName, ".")[0]
		if f == topoName {
			return loadTopoFile(path + fileName)
		}
	}
	return nil, fmt.Errorf("topology '%s' not found", topoName)
}