package ganserv

import (
	"fmt"
	"math/rand"
	"net"
	"time"
)

//Generate all ip address from a CIDR
func GetAllAddressFromCIDR(cidr string) ([]string, error) {
	ip, ipnet, err := net.ParseCIDR(cidr)
	if err != nil {
		return nil, err
	}

	var ips []string
	for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
		ips = append(ips, ip.String())
	}
	// remove network address and broadcast address
	return ips[1 : len(ips)-1], nil
}

func inc(ip net.IP) {
	for j := len(ip) - 1; j >= 0; j-- {
		ip[j]++
		if ip[j] > 0 {
			break
		}
	}
}

//Validate if a network struct is correct
func validateNetwork(n *Network) error {
	// Check if UID is a valid 16 char random ASCII string
	if len(n.UID) != 16 {
		return fmt.Errorf("UID must be 16 characters long")
	}
	for _, r := range n.UID {
		if r < '0' || ('9' < r && r < 'A') || ('Z' < r && r < 'a') || r > 'z' {
			return fmt.Errorf("UID must be a 16 char random ASCII string")
		}
	}

	// Check if Name is ASCII only
	if !isASCII(n.Name) {
		return fmt.Errorf("Name must be ASCII only")
	}

	// Check if Subnet is valid
	if n.CIDR == "" {
		return fmt.Errorf("Subnet is not set")
	}
	_, _, err := net.ParseCIDR(n.CIDR)
	if err != nil {
		//This is not a valid CIDR
		return fmt.Errorf("CIDR is not valid")
	}

	return nil
}

//Check if a string is ascii
func isASCII(s string) bool {
	for _, r := range s {
		if r > 127 {
			return false
		}
	}
	return true
}

//Generate a new random network ID
func newNetworkID() string {
	rand.Seed(time.Now().UnixNano())

	const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	const length = 16

	var result string
	for i := 0; i < length; i++ {
		result += string(chars[rand.Intn(len(chars))])
	}

	return result
}
