package libnetwork

import (
	"net"

	"github.com/Microsoft/hcsshim"
	"github.com/sirupsen/logrus"
)

type policyLists struct {
	ilb *hcsshim.PolicyList
	elb *hcsshim.PolicyList
}

var lbPolicylistMap = make(map[*loadBalancer]*policyLists)

func (n *network) addLBBackend(ip net.IP, lb *loadBalancer) {
	if len(lb.vip) == 0 {
		return
	}

	vip := lb.vip
	ingressPorts := lb.service.ingressPorts

	lb.Lock()
	defer lb.Unlock()
	//find the load balancer IP for the network.
	var sourceVIP string
	for _, e := range n.Endpoints() {
		epInfo := e.Info()
		if epInfo == nil {
			continue
		}
		if epInfo.LoadBalancer() {
			sourceVIP = epInfo.Iface().Address().IP.String()
			break
		}
	}

	if sourceVIP == "" {
		logrus.Errorf("Failed to find load balancer IP for network %s", n.Name())
		return
	}

	var endpoints []hcsshim.HNSEndpoint

	for eid, be := range lb.backEnds {
		if be.disabled {
			continue
		}
		//Call HNS to get back ID (GUID) corresponding to the endpoint.
		hnsEndpoint, err := hcsshim.GetHNSEndpointByName(eid)
		if err != nil {
			logrus.Errorf("Failed to find HNS ID for endpoint %v: %v", eid, err)
			return
		}

		endpoints = append(endpoints, *hnsEndpoint)
	}

	if policies, ok := lbPolicylistMap[lb]; ok {

		if policies.ilb != nil {
			policies.ilb.Delete()
			policies.ilb = nil
		}

		if policies.elb != nil {
			policies.elb.Delete()
			policies.elb = nil
		}
		delete(lbPolicylistMap, lb)
	}

	ilbPolicy, err := hcsshim.AddLoadBalancer(endpoints, true, sourceVIP, vip.String(), 0, 0, 0)
	if err != nil {
		logrus.Errorf("Failed to add ILB policy for service %s (%s) with endpoints %v using load balancer IP %s on network %s: %v",
			lb.service.name, vip.String(), endpoints, sourceVIP, n.Name(), err)
		return
	}

	lbPolicylistMap[lb] = &policyLists{
		ilb: ilbPolicy,
	}

	publishedPorts := make(map[uint32]uint32)

	for i, port := range ingressPorts {
		protocol := uint16(6)

		// Skip already published port
		if publishedPorts[port.PublishedPort] == port.TargetPort {
			continue
		}

		if port.Protocol == ProtocolUDP {
			protocol = 17
		}

		// check if already has udp matching to add wild card publishing
		for j := i + 1; j < len(ingressPorts); j++ {
			if ingressPorts[j].TargetPort == port.TargetPort &&
				ingressPorts[j].PublishedPort == port.PublishedPort {
				protocol = 0
			}
		}

		publishedPorts[port.PublishedPort] = port.TargetPort

		lbPolicylistMap[lb].elb, err = hcsshim.AddLoadBalancer(endpoints, false, sourceVIP, "", protocol, uint16(port.TargetPort), uint16(port.PublishedPort))
		if err != nil {
			logrus.Errorf("Failed to add ELB policy for service %s (ip:%s target port:%v published port:%v) with endpoints %v using load balancer IP %s on network %s: %v",
				lb.service.name, vip.String(), uint16(port.TargetPort), uint16(port.PublishedPort), endpoints, sourceVIP, n.Name(), err)
			return
		}
	}
}

func (n *network) rmLBBackend(ip net.IP, lb *loadBalancer, rmService bool, fullRemove bool) {
	if len(lb.vip) == 0 {
		return
	}

	if numEnabledBackends(lb) > 0 {
		// Reprogram HNS (actually VFP) with the existing backends.
		n.addLBBackend(ip, lb)
	} else {
		lb.Lock()
		defer lb.Unlock()
		logrus.Debugf("No more backends for service %s (ip:%s).  Removing all policies", lb.service.name, lb.vip.String())

		if policyLists, ok := lbPolicylistMap[lb]; ok {
			if policyLists.ilb != nil {
				if _, err := policyLists.ilb.Delete(); err != nil {
					logrus.Errorf("Failed to remove HNS ILB policylist %s: %s", policyLists.ilb.ID, err)
				}
				policyLists.ilb = nil
			}

			if policyLists.elb != nil {
				if _, err := policyLists.elb.Delete(); err != nil {
					logrus.Errorf("Failed to remove HNS ELB policylist %s: %s", policyLists.elb.ID, err)
				}
				policyLists.elb = nil
			}
			delete(lbPolicylistMap, lb)

		} else {
			logrus.Errorf("Failed to find policies for service %s (%s)", lb.service.name, lb.vip.String())
		}
	}
}

func numEnabledBackends(lb *loadBalancer) int {
	nEnabled := 0
	for _, be := range lb.backEnds {
		if !be.disabled {
			nEnabled++
		}
	}
	return nEnabled
}

func (sb *Sandbox) populateLoadBalancers(ep *Endpoint) {
}

func arrangeIngressFilterRule() {
}
