package icsnet

import (
	"fmt"
	"net"
	"strconv"
	"strings"

	"gitlab.com/cinnamon/voiceagent/icserror"
)

type IcsNetAddr struct {
	IPv4       []byte
	IPv4String string
	Port       int
}

func NewNetAddr() IcsNetAddr {
	addr := IcsNetAddr{}
	addr.IPv4 = make([]byte, 4)

	return addr
}

//format 123.123.123.123:9999
func NewNetAddrWithIPAddr(ipaddr string) IcsNetAddr {
	addr := IcsNetAddr{}
	addr.IPv4 = make([]byte, 4)

	spl := strings.Split(ipaddr, ":")
	addr.SetIPv4String(spl[0])
	var err error
	addr.Port, err = strconv.Atoi(spl[1])
	if err != nil {
		addr.Port = 0
	}

	return addr
}

func NewNetAddrWithIPPort(ip string, port int) IcsNetAddr {
	addr := IcsNetAddr{}
	addr.IPv4 = make([]byte, 4)

	addr.SetIPv4String(ip)
	addr.SetPort(port)

	return addr
}

func NewIcsNetAddrWithUDPAddr(addr *net.UDPAddr) *IcsNetAddr {
	icsaddr := &IcsNetAddr{}
	icsaddr.IPv4 = make([]byte, 4)

	icsaddr.SetIPv4String(addr.IP.String())
	icsaddr.SetPort(addr.Port)

	//fmt.Println(">>>>", icsaddr)
	return icsaddr
}

func NewIcsNetAddrWithTCPAddr(addr *net.TCPAddr) *IcsNetAddr {
	icsaddr := &IcsNetAddr{}
	icsaddr.IPv4 = make([]byte, 4)

	ip, sport, _ := net.SplitHostPort(addr.IP.String())
	port, _ := strconv.Atoi(sport)
	icsaddr.SetIPv4String(ip)
	icsaddr.SetPort(port)

	return icsaddr
}

func (a *IcsNetAddr) SetIPv4(ip []byte) {
	copy(a.IPv4, ip)
	a.IPv4String = fmt.Sprintf("%d.%d.%d.%d", a.IPv4[0], a.IPv4[1], a.IPv4[2], a.IPv4[3])
}

func (a *IcsNetAddr) SetIPv4String(ip string) {
	a.IPv4String = ip

	no := strings.Split(ip, ".")
	for iter, b := range no {
		i, err := strconv.Atoi(b)
		if err != nil {
			i = 0
		}

		a.IPv4[iter] = byte(i)
	}
}

func (a *IcsNetAddr) SetPort(port int) {
	a.Port = port
}

func (a IcsNetAddr) String() string {
	strAddr := fmt.Sprintf("%d.%d.%d.%d:%d", a.IPv4[0], a.IPv4[1], a.IPv4[2], a.IPv4[3], a.Port)
	return strAddr
}

func (a IcsNetAddr) ResolveIcsNetAddr(network string) (interface{}, *icserror.IcsError) {
	ip := fmt.Sprintf("%d.%d.%d.%d:%d", a.IPv4[0], a.IPv4[1], a.IPv4[2], a.IPv4[3], a.Port)

	if strings.Compare("tcp", network) == 0 {
		addr, err := net.ResolveTCPAddr("tcp", ip)
		if err != nil {
			icserror.ICSERRNETResolveAddrError.SetError(err)
			return nil, icserror.ICSERRNETResolveAddrError
		}
		return interface{}(*addr), nil
	} else if strings.Compare("udp", network) == 0 {
		addr, err := net.ResolveUDPAddr("udp", ip)
		if err != nil {
			icserror.ICSERRNETResolveAddrError.SetError(err)
			return nil, icserror.ICSERRNETResolveAddrError
		}
		return interface{}(*addr), nil
	}

	return nil, nil
}
