package network

import (
	"fmt"
	"net"
	"testing"
	"time"
)

func defaultRead(conn net.Conn) (b []byte, err error) {
	if err = conn.SetReadDeadline(time.Now().Add(DefaultReadTimout)); err != nil {
		return nil, err
	}

	b = Body()

	n, err := conn.Read(b)
	if err != nil {
		return nil, err
	}
	return b[:n], nil
}

func defaultWrite(conn net.Conn, p []byte) (err error) {
	if err = conn.SetWriteDeadline(time.Now().Add(DefaultWriteTimout)); err != nil {
		return err
	}
	_, err = conn.Write(p)
	if err != nil {
		return err
	}
	return nil
}

func serverTCP(address string) {
	listener, err := net.Listen(NetTCP, address)
	if err != nil {
		panic(err)
	}
	for {
		conn, err := listener.Accept()
		if err != nil {
			_ = listener.Close()
			fmt.Println("serverTCP: accept close:", err)
			return
		}
		go func(conn net.Conn) {
			for {
				b, err := defaultRead(conn)
				if err != nil {
					_ = conn.Close()
					fmt.Println("conn.Read:", err)
					return
				}
				fmt.Println("conn.Read:", Bytes(b).HexTo())
			}
		}(conn)
	}
}

func serverTCPModBus(address string) {
	listener, err := net.Listen(NetTCP, address)
	if err != nil {
		panic(err)
	}
	for {
		conn, err := listener.Accept()
		if err != nil {
			_ = listener.Close()
			fmt.Println("serverTCP: accept close:", err)
			return
		}
		go func(conn net.Conn) {
			for {
				b, err := defaultRead(conn)
				if err != nil {
					_ = conn.Close()
					fmt.Println("conn.Read:", err)
					return
				}
				fmt.Println("conn.Read:", Bytes(b))
				p := []byte("hello,world")
				if err = defaultWrite(conn, p); err != nil {
					_ = conn.Close()
					fmt.Println("conn.Write:", err)
				} else {
					fmt.Println("conn.Write:", string(p))
				}
			}
		}(conn)
	}
}

func TestTcpClient_SetAutoReconnect(t *testing.T) {
	address := "127.0.0.1:9876"
	go serverTCP(address)

	client, err := Dial(NetTCP, address)
	if err != nil {
		t.Error("Dial:", err)
		return
	}

	var count int
	for {
		_, err = client.Write([]byte(time.Now().String()))
		if err != nil {
			fmt.Println("client.Write:", err)
		} else {
			count++
			if count >= 5 && count < 10 {
				time.Sleep(5 * time.Second)
			}
			if count == 10 {
				_ = client.Close()
				fmt.Println("client.Close")
			}
			if count >= 10 {
				count = 0
			}
		}
		time.Sleep(1 * time.Second)
	}
}

func TestTcpClient_SetAutoReconnectModbus(t *testing.T) {
	address := "127.0.0.1:9876"
	go serverTCPModBus(address)

	client, err := Dial(NetTCP, address)
	if err != nil {
		t.Error("Dial:", err)
		return
	}

	var count int
	for {
		_, err = client.Write([]byte(time.Now().String()))
		if err == nil {

			b := defaultPool.Get().([]byte)
			defaultPool.Put(b)

			n, err := client.Read(b)
			if err == nil {
				fmt.Println("client.Read:", b[:n])
				count++
				if count >= 5 && count < 10 {
					time.Sleep(5 * time.Second)
				}
				if count == 10 {
					_ = client.Close()
					fmt.Println("client.Close")
				}
				if count >= 10 {
					count = 0
				}
			} else {
				fmt.Println("client.Read:", err)
			}

		} else {
			fmt.Println("client.Write:", err)
		}

		time.Sleep(1 * time.Second)
	}
}

func TestDial(t *testing.T) {
	address := "127.0.0.1:9876"
	go serverTCP(address)

	client, err := Dial(NetTCP, address)
	if err != nil {
		t.Error("Dial:", err)
		return
	}

	var count int
	for {
		_, err = client.Write([]byte(time.Now().String()))
		if err != nil {
			t.Error("client.Write:", err)
			return
		}
		count++
		if count >= 5 {
			time.Sleep(6 * time.Second)
			count = 0
		} else {
			time.Sleep(1 * time.Second)
		}
	}
}

func TestDialModBus(t *testing.T) {
	address := "127.0.0.1:9876"
	go serverTCPModBus(address)

	client, err := Dial(NetTCP, address)
	if err != nil {
		t.Error("DialModBus:", err)
		return
	}

	var count int
	for {
		_, err = client.Write([]byte(time.Now().String()))
		if err != nil {
			t.Error("client.Write:", err)
			return
		}

		b := defaultPool.Get().([]byte)
		defaultPool.Put(b)

		i, err := client.Read(b)
		if err != nil {
			t.Error("client.Read:", err)
			return
		}

		fmt.Println("client.Read:", b[:i])

		count++
		if count >= 5 {
			time.Sleep(6 * time.Second)
			count = 0
		} else {
			time.Sleep(1 * time.Second)
		}
	}
}

type mswHandler struct {
	b []byte
}

func (m *mswHandler) Create() ([]byte, error) {
	return m.b, nil
}

func TestDialModbusStatus(t *testing.T) {
	address := "127.0.0.1:9876"
	go serverTCPModBus(address)

	tcpClient, err := Dial(NetTCP, address)
	if err != nil {
		t.Error(err)
		return
	}

	ms := NewModbusClient(tcpClient, &mswHandler{b: []byte(time.Now().String())})
	defer func() {
		_ = ms.Close()
	}()

	for {
		b := Body()
		n, err := ms.Read(b)
		if err != nil {
			t.Error("client.Read:", err)
			return
		}
		time.Sleep(1 * time.Second)
		fmt.Println("client.Read:", string(b[:n]))
	}
}
