package switchy

import (
	"strings"
	"sync"

	"github.rackspace.com/gorax/clients/dcxSwitchapi"
)

func (s *SwitchClient) SwitchAPIStatus(swapi *dcxSwitchapi.Client) error {
	var err error
	for _, port := range s.SwitchPorts {
		if port.FeInt > 0 {
			port.Status, err = swapi.SwitchInterface(s.SwitchName, port.FeInt)
			if err != nil {
				return err
			}
		} else if port.Port > 0 {
			port.Status, err = swapi.SwitchPort(s.SwitchName, port.Port)
			if err != nil {
				return err
			}
		}
	}
	if err := s.SwitchAPIAggStatus(swapi); err != nil {
		return nil
	}
	return nil
}

func (s *SwitchClient) SwitchAPIAggStatus(swapi *dcxSwitchapi.Client) error {
	for _, port := range s.SwitchPorts {
		if port.Status != nil {
			if port.Status.AggregatedTo == nil {
				continue
			}
			if *port.Status.AggregatedTo != -1 && *port.Status.AggregatedTo != port.Status.Id {
				agg := s.SwitchPortByFeInt(*port.Status.AggregatedTo)
				if agg == nil {
					agg = new(SwitchPort)
					s.SwitchPorts = append(s.SwitchPorts, agg)
				}
				if agg.Status != nil {
					continue
				}
				portStatus, err := swapi.SwitchInterface(s.SwitchName, *port.Status.AggregatedTo)
				if err != nil {
					return err
				}
				agg.Status = portStatus
				if agg.PortName == "" || agg.FeInt == 0 {
					agg.PortName = portStatus.Name
					agg.FeInt = portStatus.Id
				}
			}
		}
	}
	return nil
}

func (s *SwitchClient) SwitchPortByFeInt(feInt int) *SwitchPort {
	for _, port := range s.SwitchPorts {
		if port.FeInt == feInt {
			return port
		}
	}
	return nil
}

func (s *SwitchClient) SwitchPortByName(portName string) *SwitchPort {
	portName = strings.ToLower(portName)
	for _, port := range s.SwitchPorts {
		if strings.ToLower(port.PortName) == portName {
			return port
		}
	}
	return nil
}

func MapSwitchAPIStatus(clients map[string]*SwitchClient, swapi *dcxSwitchapi.Client) {
	swChan := make(chan *SwitchClient)
	wg := new(sync.WaitGroup)
	workerStart(swChan, func(sw *SwitchClient) {
		if err := sw.SwitchAPIStatus(sw.swapi); err != nil {
			sw.Errors = append(sw.Errors, err)
		}
	}, wg)

	for _, sw := range clients {
		sw.swapi = swapi
		wg.Add(1)
		swChan <- sw
	}

	wg.Wait()
	close(swChan)
}
