/*
 * Copyright 2018-present Open Networking Foundation

 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at

 * http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package common

import (
	"flag"
	"fmt"
	"io/ioutil"
	"net"
	"strings"

	"github.com/imdario/mergo"
	log "github.com/sirupsen/logrus"
	"gopkg.in/yaml.v2"
)

var tagAllocationValues = []string{
	"unknown",
	"shared",
	"unique",
}

const (
	BP_FORMAT_MEF  = "mef"
	BP_FORMAT_IETF = "ietf"
)

type TagAllocation int

func (t TagAllocation) String() string {
	return tagAllocationValues[t]
}

func tagAllocationFromString(s string) (TagAllocation, error) {
	for i, v := range tagAllocationValues {
		if v == strings.TrimSpace(s) {
			return TagAllocation(i), nil
		}
	}
	log.WithFields(log.Fields{
		"ValidValues": strings.Join(tagAllocationValues[1:], ", "),
	}).Errorf("%s-is-not-a-valid-tag-allocation", s)
	return TagAllocation(0), fmt.Errorf("%s-is-not-a-valid-tag-allocation", s)
}

const (
	_ TagAllocation = iota
	TagAllocationShared
	TagAllocationUnique
)

type BBRCliOptions struct {
	*GlobalConfig
	BBSimIp      string
	BBSimPort    string
	BBSimApiPort string
	LogFile      string
}

type GlobalConfig struct {
	BBSim BBSimConfig
	Olt   OltConfig
	BBR   BBRConfig
}

type OltConfig struct {
	Model              string `yaml:"model"`
	Vendor             string `yaml:"vendor"`
	HardwareVersion    string `yaml:"hardware_version"`
	FirmwareVersion    string `yaml:"firmware_version"`
	DeviceId           string `yaml:"device_id"`
	DeviceSerialNumber string `yaml:"device_serial_number"`
	PonPorts           uint32 `yaml:"pon_ports"`
	NniPorts           uint32 `yaml:"nni_ports"`
	NniSpeed           uint32 `yaml:"nni_speed"`
	OnusPonPort        uint32 `yaml:"onus_per_port"`
	ID                 int    `yaml:"id"`
	OltRebootDelay     int    `yaml:"reboot_delay"`
	PortStatsInterval  int    `yaml:"port_stats_interval"`
	OmciResponseRate   uint8  `yaml:"omci_response_rate"`
	UniPorts           uint32 `yaml:"uni_ports"`
	PotsPorts          uint32 `yaml:"pots_ports"`
	NniDhcpTrapVid     uint32 `yaml:"nni_dhcp_trap_vid"`
}

type PonPortsConfig struct {
	Number uint32           `yaml:"num_pon_ports"`
	Ranges []PonRangeConfig `yaml:"ranges"`
}

type IdRange struct {
	StartId uint32 `yaml:"start"`
	EndId   uint32 `yaml:"end"`
}

type PonTechnology int

var ponTechnologyValues = []string{
	"GPON", "XGS-PON",
}

func (t PonTechnology) String() string {
	return ponTechnologyValues[t]
}

const (
	GPON PonTechnology = iota
	XGSPON
)

func PonTechnologyFromString(s string) (PonTechnology, error) {
	for i, val := range ponTechnologyValues {
		if val == s {
			return PonTechnology(i), nil
		}
	}
	log.WithFields(log.Fields{
		"ValidValues": strings.Join(ponTechnologyValues[:], ", "),
	}).Errorf("%s-is-not-a-valid-pon-technology", s)
	return -1, fmt.Errorf("%s-is-not-a-valid-pon-technology", s)
}

//Constants for default allocation ranges
const (
	defaultOnuIdStart          = 1
	defaultAllocIdStart        = 1024
	defaultGemPortIdPerAllocId = 8
	defaultGemportIdStart      = 1024
)

type PonRangeConfig struct {
	PonRange     IdRange `yaml:"pon_id_range"`
	Technology   string  `yaml:"tech"`
	OnuRange     IdRange `yaml:"onu_id_range"`
	AllocIdRange IdRange `yaml:"alloc_id_range"`
	GemportRange IdRange `yaml:"gemport_id_range"`
}

func GetPonConfigById(id uint32) (*PonRangeConfig, error) {
	if PonsConfig == nil {
		return nil, fmt.Errorf("pons-config-nil")
	}

	for _, r := range PonsConfig.Ranges {
		if id >= r.PonRange.StartId && id <= r.PonRange.EndId {
			return &r, nil
		}
	}

	return nil, fmt.Errorf("pon-config-for-id-%d-not-found", id)
}

type BBSimConfig struct {
	ConfigFile                  string
	ServiceConfigFile           string
	PonsConfigFile              string
	DhcpRetry                   bool    `yaml:"dhcp_retry"`
	AuthRetry                   bool    `yaml:"auth_retry"`
	LogLevel                    string  `yaml:"log_level"`
	LogCaller                   bool    `yaml:"log_caller"`
	Delay                       int     `yaml:"delay"`
	CpuProfile                  *string `yaml:"cpu_profile"`
	OpenOltAddress              string  `yaml:"openolt_address"`
	ApiAddress                  string  `yaml:"api_address"`
	RestApiAddress              string  `yaml:"rest_api_address"`
	LegacyApiAddress            string  `yaml:"legacy_api_address"`
	LegacyRestApiAddress        string  `yaml:"legacy_rest_api_address"`
	SadisRestAddress            string  `yaml:"sadis_rest_address"`
	SadisServer                 bool    `yaml:"sadis_server"`
	KafkaAddress                string  `yaml:"kafka_address"`
	Events                      bool    `yaml:"enable_events"`
	ControlledActivation        string  `yaml:"controlled_activation"`
	EnablePerf                  bool    `yaml:"enable_perf"`
	KafkaEventTopic             string  `yaml:"kafka_event_topic"`
	DmiServerAddress            string  `yaml:"dmi_server_address"`
	BandwidthProfileFormat      string  `yaml:"bp_format"`
	InjectOmciUnknownAttributes bool    `yaml:"inject_omci_unknown_attributes"`
}

type BBRConfig struct {
	Log       string `yaml:"log"`
	LogLevel  string `yaml:"log_level"`
	LogCaller bool   `yaml:"log_caller"`
}

type ServiceYaml struct {
	Name                string
	CTag                int    `yaml:"c_tag"`
	STag                int    `yaml:"s_tag"`
	NeedsEapol          bool   `yaml:"needs_eapol"`
	NeedsDhcp           bool   `yaml:"needs_dhcp"`
	NeedsIgmp           bool   `yaml:"needs_igmp"`
	NeedsPPPoE          bool   `yaml:"needs_pppoe"`
	CTagAllocation      string `yaml:"c_tag_allocation"`
	STagAllocation      string `yaml:"s_tag_allocation"`
	TechnologyProfileID int    `yaml:"tp_id"`
	UniTagMatch         int    `yaml:"uni_tag_match"`
	ConfigureMacAddress bool   `yaml:"configure_mac_address"`
	EnableMacLearning   bool   `yaml:"enable_mac_learning"`
	UsPonCTagPriority   uint8  `yaml:"us_pon_c_tag_priority"`
	UsPonSTagPriority   uint8  `yaml:"us_pon_s_tag_priority"`
	DsPonCTagPriority   uint8  `yaml:"ds_pon_c_tag_priority"`
	DsPonSTagPriority   uint8  `yaml:"ds_pon_s_tag_priority"`
}
type YamlServiceConfig struct {
	Workflow string
	Services []ServiceYaml `yaml:"services,flow"`
}

func (cfg *YamlServiceConfig) String() string {
	str := fmt.Sprintf("[workflow: %s, Services: ", cfg.Workflow)

	for _, s := range cfg.Services {
		str = fmt.Sprintf("%s[", str)
		str = fmt.Sprintf("%sname=%s, c_tag=%d, s_tag=%d, ",
			str, s.Name, s.CTag, s.STag)
		str = fmt.Sprintf("%sc_tag_allocation=%s, s_tag_allocation=%s, ",
			str, s.CTagAllocation, s.STagAllocation)
		str = fmt.Sprintf("%sneeds_eapol=%t, needs_dhcp=%t, needs_igmp=%t",
			str, s.NeedsEapol, s.NeedsDhcp, s.NeedsIgmp)
		str = fmt.Sprintf("%stp_id=%d, uni_tag_match=%d",
			str, s.TechnologyProfileID, s.UniTagMatch)
		str = fmt.Sprintf("%s]", str)
	}
	str = fmt.Sprintf("%s]", str)
	return str
}

var (
	Config     *GlobalConfig
	Services   []ServiceYaml
	PonsConfig *PonPortsConfig
)

// Load the BBSim configuration. This is a combination of CLI parameters and YAML files
// We proceed in this order:
// - Read CLI parameters
// - Using those we read the yaml files (config and services)
// - we merge the configuration (CLI has priority over yaml files)
func LoadConfig() {

	Config = getDefaultOps()

	cliConf := readCliParams()

	yamlConf, err := loadBBSimConf(cliConf.BBSim.ConfigFile)

	if err != nil {
		log.WithFields(log.Fields{
			"file": cliConf.BBSim.ConfigFile,
			"err":  err,
		}).Fatal("Can't read config file")
	}

	// merging Yaml and Default Values
	if err := mergo.Merge(Config, yamlConf, mergo.WithOverride); err != nil {
		log.WithFields(log.Fields{
			"err": err,
		}).Fatal("Can't merge YAML and Config")
	}

	// merging CLI values on top of the yaml ones
	if err := mergo.Merge(Config, cliConf, mergo.WithOverride); err != nil {
		log.WithFields(log.Fields{
			"err": err,
		}).Fatal("Can't merge CLI and Config")
	}

	services, err := loadBBSimServices(Config.BBSim.ServiceConfigFile)

	if err != nil {
		log.WithFields(log.Fields{
			"file": Config.BBSim.ServiceConfigFile,
			"err":  err,
		}).Fatal("Can't read services file")
	}

	Services = services

	//A blank filename means we should fall back to bbsim defaults
	if Config.BBSim.PonsConfigFile == "" {
		PonsConfig, err = getDefaultPonsConfig()
		if err != nil {
			log.WithFields(log.Fields{
				"err": err,
			}).Fatal("Can't load Pon interfaces defaults.")
		}
	} else {
		PonsConfig, err = loadBBSimPons(Config.BBSim.PonsConfigFile)

		if err != nil {
			log.WithFields(log.Fields{
				"file": Config.BBSim.PonsConfigFile,
				"err":  err,
			}).Fatal("Can't read services file")
		}
	}

	if err := validatePonsConfig(PonsConfig); err != nil {
		log.WithFields(log.Fields{
			"file": Config.BBSim.PonsConfigFile,
			"err":  err,
		}).Fatal("Invalid Pon interfaces configuration")
	}
}

func readCliParams() *GlobalConfig {

	conf := getDefaultOps()

	configFile := flag.String("config", conf.BBSim.ConfigFile, "Configuration file path")
	servicesFile := flag.String("services", conf.BBSim.ServiceConfigFile, "Service Configuration file path")
	ponsFile := flag.String("pon_port_config_file", conf.BBSim.PonsConfigFile, "Pon Interfaces Configuration file path")
	sadisBpFormat := flag.String("bp_format", conf.BBSim.BandwidthProfileFormat, "Bandwidth profile format, 'mef' or 'ietf'")

	olt_id := flag.Int("olt_id", conf.Olt.ID, "OLT device ID")
	nni := flag.Int("nni", int(conf.Olt.NniPorts), "Number of NNI ports per OLT device to be emulated")
	nni_speed := flag.Uint("nni_speed", uint(conf.Olt.NniSpeed), "Reported speed of the NNI ports in Mbps")
	pon := flag.Int("pon", int(conf.Olt.PonPorts), "Number of PON ports per OLT device to be emulated")
	onu := flag.Int("onu", int(conf.Olt.OnusPonPort), "Number of ONU devices per PON port to be emulated")
	uni := flag.Int("uni", int(conf.Olt.UniPorts), "Number of Ethernet UNI Ports per ONU device to be emulated")
	pots := flag.Int("pots", int(conf.Olt.PotsPorts), "Number of POTS UNI Ports per ONU device to be emulated")
	NniDchpTrapVid := flag.Int("nni_dhcp_trap_vid", int(conf.Olt.NniDhcpTrapVid), "Vlan to trap the DHCP packets on")

	oltRebootDelay := flag.Int("oltRebootDelay", conf.Olt.OltRebootDelay, "Time that BBSim should before restarting after a reboot")
	omci_response_rate := flag.Int("omci_response_rate", int(conf.Olt.OmciResponseRate), "Amount of OMCI messages to respond to")

	openolt_address := flag.String("openolt_address", conf.BBSim.OpenOltAddress, "IP address:port")
	api_address := flag.String("api_address", conf.BBSim.ApiAddress, "IP address:port")
	rest_api_address := flag.String("rest_api_address", conf.BBSim.RestApiAddress, "IP address:port")
	dmi_server_address := flag.String("dmi_server_address", conf.BBSim.DmiServerAddress, "IP address:port")

	profileCpu := flag.String("cpuprofile", "", "write cpu profile to file")

	logLevel := flag.String("logLevel", conf.BBSim.LogLevel, "Set the log level (trace, debug, info, warn, error)")
	logCaller := flag.Bool("logCaller", conf.BBSim.LogCaller, "Whether to print the caller filename or not")

	delay := flag.Int("delay", conf.BBSim.Delay, "The delay between ONU DISCOVERY batches in milliseconds (1 ONU per each PON PORT at a time")

	controlledActivation := flag.String("ca", conf.BBSim.ControlledActivation, "Set the mode for controlled activation of PON ports and ONUs")
	enablePerf := flag.Bool("enableperf", conf.BBSim.EnablePerf, "Setting this flag will cause BBSim to not store data like traffic schedulers, flows of ONUs etc..")
	enableEvents := flag.Bool("enableEvents", conf.BBSim.Events, "Enable sending BBSim events on configured kafka server")
	kafkaAddress := flag.String("kafkaAddress", conf.BBSim.KafkaAddress, "IP:Port for kafka")
	kafkaEventTopic := flag.String("kafkaEventTopic", conf.BBSim.KafkaEventTopic, "Ability to configure the topic on which BBSim publishes events on Kafka")
	dhcpRetry := flag.Bool("dhcpRetry", conf.BBSim.DhcpRetry, "Set this flag if BBSim should retry DHCP upon failure until success")
	authRetry := flag.Bool("authRetry", conf.BBSim.AuthRetry, "Set this flag if BBSim should retry EAPOL (Authentication) upon failure until success")
	injectOmciUnknownAttributes := flag.Bool("injectOmciUnknownAttributes", conf.BBSim.InjectOmciUnknownAttributes, "Generate a MibDB packet with Unknown Attributes")

	flag.Parse()

	conf.Olt.ID = int(*olt_id)
	conf.Olt.NniPorts = uint32(*nni)
	conf.Olt.NniSpeed = uint32(*nni_speed)
	conf.Olt.PonPorts = uint32(*pon)
	conf.Olt.UniPorts = uint32(*uni)
	conf.Olt.PotsPorts = uint32(*pots)
	conf.Olt.OnusPonPort = uint32(*onu)
	conf.Olt.NniDhcpTrapVid = uint32(*NniDchpTrapVid)
	conf.Olt.OltRebootDelay = *oltRebootDelay
	conf.Olt.OmciResponseRate = uint8(*omci_response_rate)
	conf.BBSim.ConfigFile = *configFile
	conf.BBSim.ServiceConfigFile = *servicesFile
	conf.BBSim.PonsConfigFile = *ponsFile
	conf.BBSim.CpuProfile = profileCpu
	conf.BBSim.LogLevel = *logLevel
	conf.BBSim.LogCaller = *logCaller
	conf.BBSim.Delay = *delay
	conf.BBSim.ControlledActivation = *controlledActivation
	conf.BBSim.EnablePerf = *enablePerf
	conf.BBSim.Events = *enableEvents
	conf.BBSim.KafkaAddress = *kafkaAddress
	conf.BBSim.OpenOltAddress = *openolt_address
	conf.BBSim.ApiAddress = *api_address
	conf.BBSim.RestApiAddress = *rest_api_address
	conf.BBSim.KafkaEventTopic = *kafkaEventTopic
	conf.BBSim.AuthRetry = *authRetry
	conf.BBSim.DhcpRetry = *dhcpRetry
	conf.BBSim.DmiServerAddress = *dmi_server_address
	conf.BBSim.InjectOmciUnknownAttributes = *injectOmciUnknownAttributes

	// update device id if not set
	if conf.Olt.DeviceId == "" {
		conf.Olt.DeviceId = net.HardwareAddr{0xA, 0xA, 0xA, 0xA, 0xA, byte(conf.Olt.ID)}.String()
	}

	// check that the BP format is valid
	if (*sadisBpFormat != BP_FORMAT_MEF) && (*sadisBpFormat != BP_FORMAT_IETF) {
		log.Fatalf("Invalid parameter 'bp_format', supported values are %s and %s, you provided %s", BP_FORMAT_MEF, BP_FORMAT_IETF, *sadisBpFormat)
	}
	conf.BBSim.BandwidthProfileFormat = *sadisBpFormat

	return conf
}

func getDefaultOps() *GlobalConfig {

	c := &GlobalConfig{
		BBSimConfig{
			ConfigFile:        "configs/bbsim.yaml",
			ServiceConfigFile: "configs/att-services.yaml",
			// PonsConfigFile is left intentionally blank here
			// to use the default values computed at runtime depending
			// on the loaded Services
			PonsConfigFile:              "",
			LogLevel:                    "debug",
			LogCaller:                   false,
			Delay:                       200,
			OpenOltAddress:              ":50060",
			ApiAddress:                  ":50070",
			RestApiAddress:              ":50071",
			LegacyApiAddress:            ":50072",
			LegacyRestApiAddress:        ":50073",
			SadisRestAddress:            ":50074",
			SadisServer:                 true,
			KafkaAddress:                ":9092",
			Events:                      false,
			ControlledActivation:        "default",
			EnablePerf:                  false,
			KafkaEventTopic:             "",
			DhcpRetry:                   false,
			AuthRetry:                   false,
			DmiServerAddress:            ":50075",
			BandwidthProfileFormat:      BP_FORMAT_MEF,
			InjectOmciUnknownAttributes: false,
		},
		OltConfig{
			Vendor:             "BBSim",
			Model:              "asfvolt16",
			HardwareVersion:    "emulated",
			FirmwareVersion:    "",
			DeviceSerialNumber: "BBSM00000001",
			PonPorts:           1,
			NniPorts:           1,
			NniSpeed:           10000, //Mbps
			OnusPonPort:        1,
			ID:                 0,
			OltRebootDelay:     60,
			PortStatsInterval:  20,
			OmciResponseRate:   10,
			UniPorts:           4,
			PotsPorts:          0,
			NniDhcpTrapVid:     0,
		},
		BBRConfig{
			LogLevel:  "debug",
			LogCaller: false,
		},
	}
	return c
}

func getDefaultPonsConfig() (*PonPortsConfig, error) {

	if Config == nil {
		return nil, fmt.Errorf("Config is nil")
	}
	if Services == nil {
		return nil, fmt.Errorf("Services is nil")
	}

	//The default should replicate the old way bbsim used to compute resource ranges based on the configuration
	// 1 allocId per Service * UNI
	allocIdPerOnu := uint32(Config.Olt.UniPorts * uint32(len(Services)))
	return &PonPortsConfig{
		Number: Config.Olt.PonPorts,
		Ranges: []PonRangeConfig{
			{
				PonRange:   IdRange{0, Config.Olt.PonPorts - 1},
				Technology: XGSPON.String(),
				// we need one ONU ID available per ONU, but the smaller the range the smaller the pool created in the openolt adapter
				OnuRange: IdRange{defaultOnuIdStart, defaultOnuIdStart + (Config.Olt.OnusPonPort - 1)},
				// 1 allocId per Service * UNI * ONU
				AllocIdRange: IdRange{defaultAllocIdStart, defaultAllocIdStart + (Config.Olt.OnusPonPort * allocIdPerOnu)},
				// up to 8 gemport-id per tcont/alloc-id
				GemportRange: IdRange{defaultGemportIdStart, defaultGemportIdStart + Config.Olt.OnusPonPort*allocIdPerOnu*defaultGemPortIdPerAllocId},
			},
		},
	}, nil
}

// LoadBBSimConf loads the BBSim configuration from a YAML file
func loadBBSimConf(filename string) (*GlobalConfig, error) {
	yamlConfig := getDefaultOps()

	yamlFile, err := ioutil.ReadFile(filename)
	if err != nil {
		log.WithFields(log.Fields{
			"err":      err,
			"filename": filename,
		}).Error("Cannot load BBSim configuration file. Using defaults.")
		return yamlConfig, nil
	}

	err = yaml.Unmarshal(yamlFile, yamlConfig)
	if err != nil {
		return nil, err
	}

	return yamlConfig, nil
}

// loadBBSimPons loads the configuration of PON interfaces from a YAML file
func loadBBSimPons(filename string) (*PonPortsConfig, error) {
	yamlPonsConfig, err := getDefaultPonsConfig()
	if err != nil {
		log.WithFields(log.Fields{
			"err": err,
		}).Error("Can't load Pon interfaces defaults.")
		return nil, err
	}

	yamlFile, err := ioutil.ReadFile(filename)
	if err != nil {
		log.WithFields(log.Fields{
			"err":      err,
			"filename": filename,
		}).Error("Cannot load Pon interfaces configuration file. Using defaults.")
		return yamlPonsConfig, nil
	}

	err = yaml.Unmarshal(yamlFile, yamlPonsConfig)
	if err != nil {
		return nil, err
	}

	return yamlPonsConfig, nil
}

// validatePonsConfig checks if the configuration to use for the definition of Pon interfaces is valid
func validatePonsConfig(pons *PonPortsConfig) error {

	if pons.Number == 0 {
		return fmt.Errorf("no-pon-ports")
	}

	definedPorts := make([]int, pons.Number)

	for rIndex, resRange := range pons.Ranges {
		if _, err := PonTechnologyFromString(resRange.Technology); err != nil {
			return err
		}

		if resRange.PonRange.EndId < resRange.PonRange.StartId {
			return fmt.Errorf("invalid-pon-ports-limits-in-range-%d", rIndex)
		}

		//Keep track of the defined pons
		for p := resRange.PonRange.StartId; p <= resRange.PonRange.EndId; p++ {
			if p > uint32(len(definedPorts)-1) {
				return fmt.Errorf("pon-port-%d-in-range-%d-but-max-is-%d", p, rIndex, pons.Number-1)
			}
			definedPorts[p]++

			if definedPorts[p] > 1 {
				return fmt.Errorf("pon-port-%d-has-duplicate-definition-in-range-%d", p, rIndex)
			}
		}

		if resRange.OnuRange.EndId < resRange.OnuRange.StartId {
			return fmt.Errorf("invalid-onus-limits-in-range-%d", rIndex)
		}
		if resRange.AllocIdRange.EndId < resRange.AllocIdRange.StartId {
			return fmt.Errorf("invalid-allocid-limits-in-range-%d", rIndex)
		}
		if resRange.GemportRange.EndId < resRange.GemportRange.StartId {
			return fmt.Errorf("invalid-gemport-limits-in-range-%d", rIndex)
		}
	}

	//Check if the ranges define all the pons
	for i, num := range definedPorts {
		if num < 1 {
			return fmt.Errorf("pon-port-%d-is-not-defined-in-ranges", i)
		}
	}

	return nil
}

// LoadBBSimServices parses a file describing the services that need to be created for each UNI
func loadBBSimServices(filename string) ([]ServiceYaml, error) {

	yamlServiceCfg := YamlServiceConfig{}

	yamlFile, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	err = yaml.Unmarshal([]byte(yamlFile), &yamlServiceCfg)
	if err != nil {
		return nil, err
	}

	for _, service := range yamlServiceCfg.Services {

		if service.CTagAllocation == "" || service.STagAllocation == "" {
			log.Fatal("c_tag_allocation and s_tag_allocation are mandatory fields")
		}

		if _, err := tagAllocationFromString(string(service.CTagAllocation)); err != nil {
			log.WithFields(log.Fields{
				"err": err,
			}).Fatal("c_tag_allocation is not valid")
		}
	}

	log.WithFields(log.Fields{
		"services": yamlServiceCfg.String(),
	}).Debug("BBSim services description correctly loaded")
	return yamlServiceCfg.Services, nil
}

// This is only used by BBR
func GetBBROpts() BBRCliOptions {

	bbsimIp := flag.String("bbsimIp", "127.0.0.1", "BBSim IP")
	bbsimPort := flag.String("bbsimPort", "50060", "BBSim Port")
	bbsimApiPort := flag.String("bbsimApiPort", "50070", "BBSim API Port")
	logFile := flag.String("logfile", "", "Log to a file")

	LoadConfig()

	bbrOptions := BBRCliOptions{
		Config,
		*bbsimIp,
		*bbsimPort,
		*bbsimApiPort,
		*logFile,
	}

	return bbrOptions
}
