package overlay

import (
	"encoding/json"
	"fmt"
	"net"
	"strconv"
	"strings"
	"sync"

	"github.com/Microsoft/hcsshim"
	"github.com/docker/libnetwork/driverapi"
	"github.com/docker/libnetwork/netlabel"
	"github.com/docker/libnetwork/portmapper"
	"github.com/docker/libnetwork/types"
	"github.com/sirupsen/logrus"
)

var (
	hostMode  bool
	networkMu sync.Mutex
)

type networkTable map[string]*network

type subnet struct {
	vni      uint32
	subnetIP *net.IPNet
	gwIP     *net.IP
}

type subnetJSON struct {
	SubnetIP string
	GwIP     string
	Vni      uint32
}

type network struct {
	id              string
	name            string
	hnsID           string
	providerAddress string
	interfaceName   string
	endpoints       endpointTable
	driver          *driver
	initEpoch       int
	initErr         error
	subnets         []*subnet
	secure          bool
	portMapper      *portmapper.PortMapper
	sync.Mutex
}

func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
	return nil, types.NotImplementedErrorf("not implemented")
}

func (d *driver) NetworkFree(id string) error {
	return types.NotImplementedErrorf("not implemented")
}

func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
	var (
		networkName   string
		interfaceName string
		staleNetworks []string
	)

	if id == "" {
		return fmt.Errorf("invalid network id")
	}

	if nInfo == nil {
		return fmt.Errorf("invalid network info structure")
	}

	if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" {
		return types.BadRequestErrorf("ipv4 pool is empty")
	}

	staleNetworks = make([]string, 0)
	vnis := make([]uint32, 0, len(ipV4Data))

	existingNetwork := d.network(id)
	if existingNetwork != nil {
		logrus.Debugf("Network preexists. Deleting %s", id)
		err := d.DeleteNetwork(id)
		if err != nil {
			logrus.Errorf("Error deleting stale network %s", err.Error())
		}
	}

	n := &network{
		id:         id,
		driver:     d,
		endpoints:  endpointTable{},
		subnets:    []*subnet{},
		portMapper: portmapper.New(""),
	}

	genData, ok := option[netlabel.GenericData].(map[string]string)

	if !ok {
		return fmt.Errorf("Unknown generic data option")
	}

	for label, value := range genData {
		switch label {
		case "com.docker.network.windowsshim.networkname":
			networkName = value
		case "com.docker.network.windowsshim.interface":
			interfaceName = value
		case "com.docker.network.windowsshim.hnsid":
			n.hnsID = value
		case netlabel.OverlayVxlanIDList:
			vniStrings := strings.Split(value, ",")
			for _, vniStr := range vniStrings {
				vni, err := strconv.Atoi(vniStr)
				if err != nil {
					return fmt.Errorf("invalid vxlan id value %q passed", vniStr)
				}

				vnis = append(vnis, uint32(vni))
			}
		}
	}

	// If we are getting vnis from libnetwork, either we get for
	// all subnets or none.
	if len(vnis) < len(ipV4Data) {
		return fmt.Errorf("insufficient vnis(%d) passed to overlay. Windows driver requires VNIs to be prepopulated", len(vnis))
	}

	for i, ipd := range ipV4Data {
		s := &subnet{
			subnetIP: ipd.Pool,
			gwIP:     &ipd.Gateway.IP,
		}

		if len(vnis) != 0 {
			s.vni = vnis[i]
		}

		d.Lock()
		for _, network := range d.networks {
			found := false
			for _, sub := range network.subnets {
				if sub.vni == s.vni {
					staleNetworks = append(staleNetworks, network.id)
					found = true
					break
				}
			}
			if found {
				break
			}
		}
		d.Unlock()

		n.subnets = append(n.subnets, s)
	}

	for _, staleNetwork := range staleNetworks {
		d.DeleteNetwork(staleNetwork)
	}

	n.name = networkName
	if n.name == "" {
		n.name = id
	}

	n.interfaceName = interfaceName

	if nInfo != nil {
		if err := nInfo.TableEventRegister(ovPeerTable, driverapi.EndpointObject); err != nil {
			return err
		}
	}

	d.addNetwork(n)

	err := d.createHnsNetwork(n)

	if err != nil {
		d.deleteNetwork(id)
	} else {
		genData["com.docker.network.windowsshim.hnsid"] = n.hnsID
	}

	return err
}

func (d *driver) DeleteNetwork(nid string) error {
	if nid == "" {
		return fmt.Errorf("invalid network id")
	}

	n := d.network(nid)
	if n == nil {
		return types.ForbiddenErrorf("could not find network with id %s", nid)
	}

	_, err := hcsshim.HNSNetworkRequest("DELETE", n.hnsID, "")
	if err != nil {
		return types.ForbiddenErrorf(err.Error())
	}

	d.deleteNetwork(nid)

	return nil
}

func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
	return nil
}

func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
	return nil
}

func (d *driver) addNetwork(n *network) {
	d.Lock()
	d.networks[n.id] = n
	d.Unlock()
}

func (d *driver) deleteNetwork(nid string) {
	d.Lock()
	delete(d.networks, nid)
	d.Unlock()
}

func (d *driver) network(nid string) *network {
	d.Lock()
	defer d.Unlock()
	return d.networks[nid]
}

// func (n *network) restoreNetworkEndpoints() error {
// 	logrus.Infof("Restoring endpoints for overlay network: %s", n.id)

// 	hnsresponse, err := hcsshim.HNSListEndpointRequest("GET", "", "")
// 	if err != nil {
// 		return err
// 	}

// 	for _, endpoint := range hnsresponse {
// 		if endpoint.VirtualNetwork != n.hnsID {
// 			continue
// 		}

// 		ep := n.convertToOverlayEndpoint(&endpoint)

// 		if ep != nil {
// 			logrus.Debugf("Restored endpoint:%s Remote:%t", ep.id, ep.remote)
// 			n.addEndpoint(ep)
// 		}
// 	}

// 	return nil
// }

func (n *network) convertToOverlayEndpoint(v *hcsshim.HNSEndpoint) *endpoint {
	ep := &endpoint{
		id:        v.Name,
		profileID: v.Id,
		nid:       n.id,
		remote:    v.IsRemoteEndpoint,
	}

	mac, err := net.ParseMAC(v.MacAddress)

	if err != nil {
		return nil
	}

	ep.mac = mac
	ep.addr = &net.IPNet{
		IP:   v.IPAddress,
		Mask: net.CIDRMask(32, 32),
	}

	return ep
}

func (d *driver) createHnsNetwork(n *network) error {

	subnets := []hcsshim.Subnet{}

	for _, s := range n.subnets {
		subnet := hcsshim.Subnet{
			AddressPrefix: s.subnetIP.String(),
		}

		if s.gwIP != nil {
			subnet.GatewayAddress = s.gwIP.String()
		}

		vsidPolicy, err := json.Marshal(hcsshim.VsidPolicy{
			Type: "VSID",
			VSID: uint(s.vni),
		})

		if err != nil {
			return err
		}

		subnet.Policies = append(subnet.Policies, vsidPolicy)
		subnets = append(subnets, subnet)
	}

	network := &hcsshim.HNSNetwork{
		Name:               n.name,
		Type:               d.Type(),
		Subnets:            subnets,
		NetworkAdapterName: n.interfaceName,
		AutomaticDNS:       true,
	}

	configurationb, err := json.Marshal(network)
	if err != nil {
		return err
	}

	configuration := string(configurationb)
	logrus.Infof("HNSNetwork Request =%v", configuration)

	hnsresponse, err := hcsshim.HNSNetworkRequest("POST", "", configuration)
	if err != nil {
		return err
	}

	n.hnsID = hnsresponse.Id
	n.providerAddress = hnsresponse.ManagementIP

	return nil
}

// contains return true if the passed ip belongs to one the network's
// subnets
func (n *network) contains(ip net.IP) bool {
	for _, s := range n.subnets {
		if s.subnetIP.Contains(ip) {
			return true
		}
	}

	return false
}

// getSubnetforIP returns the subnet to which the given IP belongs
func (n *network) getSubnetforIP(ip *net.IPNet) *subnet {
	for _, s := range n.subnets {
		// first check if the mask lengths are the same
		i, _ := s.subnetIP.Mask.Size()
		j, _ := ip.Mask.Size()
		if i != j {
			continue
		}
		if s.subnetIP.Contains(ip.IP) {
			return s
		}
	}
	return nil
}

// getMatchingSubnet return the network's subnet that matches the input
func (n *network) getMatchingSubnet(ip *net.IPNet) *subnet {
	if ip == nil {
		return nil
	}
	for _, s := range n.subnets {
		// first check if the mask lengths are the same
		i, _ := s.subnetIP.Mask.Size()
		j, _ := ip.Mask.Size()
		if i != j {
			continue
		}
		if s.subnetIP.IP.Equal(ip.IP) {
			return s
		}
	}
	return nil
}
