#include "TcpEntity.h"
#include "common/Utils.h"
#include <sstream>
#include <iomanip>
#include <iostream>

static std::string ToHexText(std::string s)
{
    std::stringstream ss;
    for (unsigned int i = 0; i < s.size(); ++i)
    {
        unsigned char ch = s[i];
        ss << std::setw(2) << std::setfill('0') << std::hex << std::uppercase << (int)ch << ((i < s.size() - 1) ? " " : "");
    }
    return ss.str();
}

TcpEntity::TcpEntity()
{
}
TcpEntity::~TcpEntity()
{
}

void TcpEntity::setAddr(string addr, int port, int commtype)
{
    this->addr = addr;
    this->port = port;
    this->commtype = commtype;
}


void TcpEntity::setReconnect(int ms)
{
    tReconnect_ = ms;
}

int TcpEntity::start()
{
    if (alive) { return 1; }
    alive = true;

    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
    {
        return -1;
    }

    sockaddr.sin_family = AF_INET;
    sockaddr.sin_port = htons(port);
    sockaddr.sin_addr.S_un.S_addr = ((commtype != 0) ? inet_addr(addr.c_str()) : htonl(INADDR_ANY));

    std::thread([=]() { 
        //if (isRequestClose_) { break; }
        //std::this_thread::sleep_for(std::chrono::milliseconds(1000));

        std::cout << "TCP thread start ..." << std::endl;
        if ((commtype != 0))
        {
            this->runClientLoop();
        }
        else
        {
            this->runServerLoop();
        }
        alive = false;
    }).detach();
    return 0;
}


void TcpEntity::runServerLoop()
{
    sock = ::socket(AF_INET, SOCK_STREAM, 0);
    // 绑定套接字 【注意】functional中定义了bind与winsock2的定义发生重载导致异常，这里需要使用::bind(加::) 
    if (::bind(sock, (SOCKADDR*)&sockaddr, sizeof(SOCKADDR)) == SOCKET_ERROR)
    {
        std::cout << "TCP server bind [" << getAddrPort() << "] failed." << std::endl;
        return;
    }
    // 启动监听，准备接收客户请求
    if (::listen(sock, 5) == SOCKET_ERROR)
    {
        std::cout << "TCP server listen [" << getAddrPort() << "] failed." << std::endl;
        return;
    }

    int addrlen = sizeof(SOCKADDR);
    while (1)
    {
        if (isCloseRequest) { break; }

        // 等待client连接请求
        Client client;
        client.sock = ::accept(sock, (SOCKADDR*)&client.sockaddr, &addrlen);
        if (client.sock == INVALID_SOCKET)
        {
            break;
        }

        // client连接成功，存储信息
        client.host = inet_ntoa(client.sockaddr.sin_addr);
        vecClient.push_back(client);

        // 创建client处理线程
        std::thread th([=]() { this->runServerRecvLoop(client, client.host); });
        th.detach();
    }

    // 客户端的连接关闭
    for (auto iter = vecClient.begin(); iter != vecClient.end(); ++iter)
    {
        ::closesocket(iter->sock);
        vecClient.erase(iter);
    }

    // 关闭socket
    ::closesocket(sock);
    isCloseRequest = false;
}

void TcpEntity::runServerRecvLoop(Client client, std::string client_name)
{
    std::vector<char> buf(10240, 0);
    while (1)
    {
        if (isCloseRequest || !alive) { break; }

        // 接收数据
        memset(buf.data(), 0, buf.size());
        int n = ::recv(client.sock, &buf[0], buf.size(), 0);
        // 需要判断 errno是否等于 EINTR 。如果errno == EINTR 则说明recv函数是由于程序接收到信号后返回的，socket连接还是正常的
        if (n <= 0 && GetLastError() != EINTR)
        {
            // 客户端连接异常（关闭）
            break;
        }
        else
        {
        }
    }
    // 连接关闭
    for (auto iter = vecClient.begin(); iter != vecClient.end(); ++iter)
    {
        if (iter->sock == client.sock)
        {
            vecClient.erase(iter);
            break;
        }
    }
}

void TcpEntity::runClientLoop()
{
    // 数据缓存
    std::vector<char> buf(10240, 0);

    while (1)
    {
        if (isCloseRequest) { break; }

        //创建套接字，向服务器发出连接请求
        sock = ::socket(AF_INET, SOCK_STREAM, 0);
        if (::connect(sock, (SOCKADDR*)&sockaddr, sizeof(SOCKADDR)) != SOCKET_ERROR)
        {
            isConnected = true;
            std::cout << "TCP client connect to [" << getAddrPort() << "] success." << std::endl;

            // 连接服务器成功，循环等待接受消息
            while (1)
            {
                if (isCloseRequest) { break; }

                memset(buf.data(), 0, buf.size());
                int n = ::recv(sock, buf.data(), buf.size(), 0);
                if (n <= 0 && GetLastError() != EINTR)
                {
                    // TCP通讯异常， 关闭连接
                    ::closesocket(sock);
                    isConnected = false;
                    break;
                } 
                else
                {
                    // 处理消息
                }
            }
        }
        else
        {
            isConnected = false;
            std::cout << "TCP client connect to [" << getAddrPort() << "] failed." << std::endl;
        }

        // 连接异常
        if (tReconnect_ > 0) 
        {
            // 重新连接
            std::cout << "TCP client [" << getAddrPort() << "] reconnect (" << tReconnect_ << ")." << std::endl;
            //std::this_thread::sleep_for(std::chrono::microseconds(tReconnect_));
            Sleep(tReconnect_);
        }
        else
        {
            // 关闭线程
            std::cout << "TCP client [" << getAddrPort() << "] close." << std::endl;
            break;
        }
    }
    if (sock != INVALID_SOCKET)
    {
        ::closesocket(sock);
        sock = INVALID_SOCKET;
        isConnected = false;
    }
    if (isCloseRequest)
    {
    }
    isCloseRequest = false;
}

bool TcpEntity::write(std::string data)
{
    if (commtype == 0)
    {
        // #服务端
        if (vecClient.size() <= 0) { return false; }
        for (auto& client : vecClient)
        {
            std::string clientAddr = inet_ntoa(client.sockaddr.sin_addr);
            ::send(client.sock, data.c_str(), data.size(), 0);
        }
        return true;
    }
    else
    {
        // #客户端
        if (sock == INVALID_SOCKET) { return false; }
        int len = ::send(sock, data.c_str(), data.size(), 0);
        return (len > 0);
    }
}
