package network

import (
	"io"
	"net"
	"time"
)

// Body 通过 defaultPool 分配 byte 数组
func Body() (p Bytes) {
	p = defaultPool.Get().(Bytes)
	defaultPool.Put(p)
	return
}

// Dial 拨号. network 可选 NetTCP 或 NetUDP 表示使用 TCP 或 UDP 协议, address 为服务器地址
// Dial 实现 net.Conn 接口
func Dial(network, address string) (net.Conn, error) {
	return DialTimout(network, address, DefaultDialTimout)
}

// DialTimout 拨号并指定超时时间
func DialTimout(network, address string, timout time.Duration) (net.Conn, error) {
	conn, err := net.DialTimeout(network, address, timout)
	if err != nil {
		return nil, err
	}
	switch network {
	case NetTCP:
		return createTCPClient(conn), nil
	case NetUDP:
		fallthrough
	default:
		return conn, nil
	}
}

func Listen(network, address string) (net.Listener, error) {
	switch network {
	case NetTCP:
		return ListenTCP(network, address)
	default:
		return net.Listen(network, address)
	}
}

func ListenTCP(network, address string) (*TCPListener, error) {
	tcpAddr, err := net.ResolveTCPAddr(network, address)
	if err != nil {
		return nil, err
	}
	listener, err := net.ListenTCP(network, tcpAddr)
	if err != nil {
		return nil, err
	}
	return &TCPListener{Listener: listener}, nil
}

// NewModbusClient 每秒使用 data 创建数据并发送至服务器
// modbusClient 每 1 秒调用 ModbusCreator 创建需要写入的数据并发送至服务器, 然后将服务器返回的数据保存在内部.
// Read 即获取服务器返回的数据, 当 Read 返回非 ErrReconnect 的错误时, 应调用 Close 关闭
// Write 始终返回 len(p) 和 nil
func NewModbusClient(conn net.Conn, data ModbusCreator) io.ReadWriteCloser {
	return createModbusClient(conn, data)
}
