package ipfunc

import (
	"errors"
	"fmt"
	"net"
	"sync"
)

type IPSubnet struct {
	freeIPs []string
	mux sync.Mutex
}

func NewIPSubnet(network string) (IPSubnet, error)  {
	i := IPSubnet{}

	ip, ipnet, err := net.ParseCIDR(network)
	if err != nil {
		return IPSubnet{}, fmt.Errorf("Cant create IPSubnet, input ip cant pase: %w", err)
	}

	var ips []string
	for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
		ips = append(ips, ip.String())
	}

	lenIPs := len(ips)
	switch {
	case lenIPs < 2:
		i.freeIPs = ips

	default:
		i.freeIPs = ips[1 : len(ips)-1]
	}


	return i, nil
}

func (i *IPSubnet) GetNextFreeIP() (string, error) {
	if len(i.freeIPs) == 0 {
		return "", errors.New("No free IP")
	}

	i.mux.Lock()
	defer i.mux.Unlock()

	rip := i.freeIPs[0]
	i.remove(rip)
	return rip, nil
}

func (i *IPSubnet) remove (ip string)  {
	var newips []string
	for _, oneIp := range i.freeIPs {
		if oneIp != ip {
			newips = append(newips, oneIp)
		}
	}

	i.freeIPs = newips
}

func (i *IPSubnet)Remove(ip string)  {
	i.mux.Lock()
	defer i.mux.Unlock()

	i.remove(ip)
}

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