package connectivity

import (
	"fmt"
	"net"
	"strings"
)

type localListenService struct {
	l net.Listener
}

type localProvider struct {
}

// NewLocalACN returns a for testing use only local clearnet implementation of a ACN interface
func NewLocalACN() ACN {
	return &localProvider{}
}

func (lp *localProvider) GetStatusCallback() func(int, string) {
	return func(int, string) {}
}

func (lp *localProvider) GetVersionCallback() func(string) {
	return func(string) {}
}

func (ls *localListenService) AddressFull() string {
	return ls.l.Addr().String()
}

func (ls *localListenService) AddressIdentity() string {
	return ls.l.Addr().String()
}

func (ls *localListenService) Accept() (net.Conn, error) {
	return ls.l.Accept()
}

func (ls *localListenService) Close() {
	ls.l.Close()
}

func (lp *localProvider) GetInfo(addr string) (map[string]string, error) {
	return nil, nil
}

// GetBootstrapStatus returns an int 0-100 on the percent the bootstrapping of the underlying network is at and an optional string message
func (lp *localProvider) GetBootstrapStatus() (int, string) {
	return 100, "Done"
}

func (lp *localProvider) SetStatusCallback(callback func(int, string)) {
	// nop
}

func (lp *localProvider) SetVersionCallback(callback func(string)) {
	// nop
}

func (lp *localProvider) GetPID() (int, error) {
	return 0, nil
}

func (lp *localProvider) GetVersion() string {
	return "0.1"
}

// WaitTillBootstrapped Blocks until underlying network is bootstrapped
func (lp *localProvider) WaitTillBootstrapped() error {
	return nil
}

func (lp *localProvider) Listen(identity PrivateKey, port int) (ListenService, error) {
	l, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%v", port))
	return &localListenService{l}, err
}

func (lp *localProvider) Open(hostname string) (net.Conn, string, error) {
	// Localhost (127.0.0.1:55555|jlq67qzo6s4yp3sp) for testing
	addrParts := strings.Split(hostname, "|")
	tcpAddr, err := net.ResolveTCPAddr("tcp", addrParts[0])
	if err != nil {
		return nil, "", CannotResolveLocalTCPAddressError
	}
	conn, err := net.DialTCP("tcp", nil, tcpAddr)
	if err != nil {
		return nil, "", CannotDialLocalTCPAddressError
	}
	// return just the onion address, not the local override for the hostname
	return conn, addrParts[1], nil

}

func (lp *localProvider) Restart() {
	//noop
}

func (lp *localProvider) Close() {

}
