package main

import (
	"strings"

	"code.fbi.h-da.de/danet/gosdn/models/generated/arista"
	"github.com/openconfig/ygot/ygot"
)

func enableRouting(model *arista.Device) error {
	// if model.NetworkInstances == nil {
	//var enableRouting = true
	model.NetworkInstances = &arista.OpenconfigNetworkInstance_NetworkInstances{}
	instance, err := model.NetworkInstances.NewNetworkInstance("default")
	if err != nil {
		return err
	}

	instance.Config = &arista.OpenconfigNetworkInstance_NetworkInstances_NetworkInstance_Config{
		//Enabled: &enableRouting,
		// 1 == DEFAULT_INSTANCE
		Type: arista.E_OpenconfigNetworkInstanceTypes_NETWORK_INSTANCE_TYPE(1),
		// 1 == OpenconfigTypes_ADDRESS_FAMILY_IPV4
		//EnabledAddressFamilies: []arista.E_OpenconfigTypes_ADDRESS_FAMILY{
		//	1,
		//},
	}

	return nil
}

func setIPOnInterface(model *arista.Device, interfaceName string, ipAddress string, prefix int) {
	if model.Interfaces == nil {
		model.Interfaces = &arista.OpenconfigInterfaces_Interfaces{}
	}

	_, ok := model.Interfaces.Interface[interfaceName]
	if !ok {
		_, err := model.Interfaces.NewInterface(interfaceName)
		if err != nil {
			panic(err)
		}
	}

	model.Interfaces.Interface[interfaceName].Config = &arista.OpenconfigInterfaces_Interfaces_Interface_Config{
		Enabled:      ygot.Bool(true),
		LoopbackMode: ygot.Bool(false),
		Mtu:          ygot.Uint16(0),
		Name:         ygot.String(interfaceName),
		Tpid:         arista.E_OpenconfigVlanTypes_TPID_TYPES(1),
		Type:         arista.E_IETFInterfaces_InterfaceType(88),
	}

	model.Interfaces.Interface[interfaceName].Name = ygot.String(interfaceName)

	if model.Interfaces.Interface[interfaceName].Subinterfaces == nil {
		model.Interfaces.Interface[interfaceName].Subinterfaces = &arista.OpenconfigInterfaces_Interfaces_Interface_Subinterfaces{}
	}

	if model.Interfaces.Interface[interfaceName].Subinterfaces.Subinterface[0] == nil {
		_, err := model.Interfaces.Interface[interfaceName].Subinterfaces.NewSubinterface(0)
		if err != nil {
			panic(err)
		}
	}

	model.Interfaces.Interface[interfaceName].Subinterfaces.Subinterface[0].Config = &arista.OpenconfigInterfaces_Interfaces_Interface_Subinterfaces_Subinterface_Config{
		Enabled: ygot.Bool(true),
		Index:   ygot.Uint32(0),
	}

	model.Interfaces.Interface[interfaceName].Subinterfaces.Subinterface[0].Ipv4 = &arista.OpenconfigInterfaces_Interfaces_Interface_Subinterfaces_Subinterface_Ipv4{
		Addresses: &arista.OpenconfigInterfaces_Interfaces_Interface_Subinterfaces_Subinterface_Ipv4_Addresses{},
	}

	if model.Interfaces.Interface[interfaceName].Subinterfaces.Subinterface[0].Ipv4.Addresses.Address[ipAddress] == nil {
		_, err := model.Interfaces.Interface[interfaceName].Subinterfaces.Subinterface[0].Ipv4.Addresses.NewAddress(ipAddress)
		if err != nil {
			panic(err)
		}

		model.Interfaces.Interface[interfaceName].Subinterfaces.Subinterface[0].Ipv4.Addresses.Address[ipAddress].Config = &arista.OpenconfigInterfaces_Interfaces_Interface_Subinterfaces_Subinterface_Ipv4_Addresses_Address_Config{
			Ip:           ygot.String(ipAddress),
			PrefixLength: ygot.Uint8(uint8(prefix)),
		}

		model.Interfaces.Interface[interfaceName].Subinterfaces.Subinterface[0].Ipv4.Config = &arista.OpenconfigInterfaces_Interfaces_Interface_Subinterfaces_Subinterface_Ipv4_Config{
			Enabled: ygot.Bool(true),
		}
	}
}

func setRoutingTable(model *arista.Device, routePrefix string, nextHopIP string) {
	if model.NetworkInstances.NetworkInstance["default"] == nil {
		_, err := model.NetworkInstances.NewNetworkInstance("default")
		if err != nil {
			panic(err)
		}
	}

	model.NetworkInstances.NetworkInstance["default"].Protocols = &arista.OpenconfigNetworkInstance_NetworkInstances_NetworkInstance_Protocols{}
	// OpenconfigPolicyTypes_INSTALL_PROTOCOL_TYPE_DIRECTLY_CONNECTED = 2
	protocol, err := model.NetworkInstances.NetworkInstance["default"].Protocols.NewProtocol(2, "DIRECTLY_CONNECTED")
	if err != nil {
		panic(err)
	}

	protocol.Config = &arista.OpenconfigNetworkInstance_NetworkInstances_NetworkInstance_Protocols_Protocol_Config{
		Identifier: arista.OpenconfigPolicyTypes_INSTALL_PROTOCOL_TYPE_DIRECTLY_CONNECTED,
		Name:       ygot.String("DIRECTLY_CONNECTED"),
	}

	// E_OpenconfigPolicyTypes_INSTALL_PROTOCOL_TYPE = 10
	protocolStatic, err := model.NetworkInstances.NetworkInstance["default"].Protocols.NewProtocol(10, "STATIC")
	if err != nil {
		panic(err)
	}

	protocolStatic.Config = &arista.OpenconfigNetworkInstance_NetworkInstances_NetworkInstance_Protocols_Protocol_Config{
		Identifier: arista.OpenconfigPolicyTypes_INSTALL_PROTOCOL_TYPE_STATIC,
		Name:       ygot.String("STATIC"),
	}

	protocolStatic.StaticRoutes = &arista.OpenconfigNetworkInstance_NetworkInstances_NetworkInstance_Protocols_Protocol_StaticRoutes{}
	_, err = protocolStatic.StaticRoutes.NewStatic(routePrefix)
	if err != nil {
		panic(err)
	}
	protocolStatic.StaticRoutes.Static[routePrefix].Config = &arista.OpenconfigNetworkInstance_NetworkInstances_NetworkInstance_Protocols_Protocol_StaticRoutes_Static_Config{
		Prefix: ygot.String(routePrefix),
	}

	protocolStatic.StaticRoutes.Static[routePrefix].NextHops = &arista.OpenconfigNetworkInstance_NetworkInstances_NetworkInstance_Protocols_Protocol_StaticRoutes_Static_NextHops{}
	// Index Example = "AUTO_1_10-13-37-2"
	nextHopIPIndex := strings.ReplaceAll(nextHopIP, ".", "_")
	nextHopIPIndex = "AUTO_" + nextHopIPIndex
	_, err = protocolStatic.StaticRoutes.Static[routePrefix].NextHops.NewNextHop(nextHopIPIndex)
	if err != nil {
		panic(err)
	}

	protocolStatic.StaticRoutes.Static[routePrefix].NextHops.NextHop[nextHopIPIndex].Config = &arista.OpenconfigNetworkInstance_NetworkInstances_NetworkInstance_Protocols_Protocol_StaticRoutes_Static_NextHops_NextHop_Config{
		Index:   ygot.String(nextHopIPIndex),
		Metric:  ygot.Uint32(1),
		NextHop: arista.UnionString(nextHopIP),
	}
}
