package pkg

import (
	"bytes"
	log "github.com/sirupsen/logrus"
	"k8s.io/apimachinery/pkg/util/sets"
	"net"
	"strings"
)

// DetectAndDisableConflictDevice will detect conflict route table and try to disable device
// 1, get route table
// 2, detect conflict
// 3, disable device
func DetectAndDisableConflictDevice(origin string) error {
	routeTable, err := getRouteTable()
	if err != nil {
		return err
	}
	conflict := detectConflictDevice(origin, routeTable)
	if len(conflict) != 0 {
		log.Infof("those device: %s will to be disabled because of route conflict with %s", strings.Join(conflict, ","), origin)
	}
	err = disableDevice(conflict)
	return err
}

func detectConflictDevice(origin string, routeTable map[string][]*net.IPNet) []string {
	var conflict = sets.NewString()
	vpnRoute := routeTable[origin]
	for k, originRoute := range routeTable {
		if k == origin {
			continue
		}
	out:
		for _, originNet := range originRoute {
			for _, vpnNet := range vpnRoute {
				// like 255.255.0.0/16 should not take effect
				if bytes.Equal(originNet.IP, originNet.Mask) || bytes.Equal(vpnNet.IP, vpnNet.Mask) {
					continue
				}
				if vpnNet.Contains(originNet.IP) || originNet.Contains(vpnNet.IP) {
					originMask, _ := originNet.Mask.Size()
					vpnMask, _ := vpnNet.Mask.Size()
					// means interface: k is more precisely, traffic will go to interface k because route table feature
					// mare precisely is preferred
					if originMask > vpnMask {
						conflict.Insert(k)
						break out
					}
				}
			}
		}
	}
	return conflict.Delete(origin).List()
}
