#include "coroutine_hook.hpp"
#include "reactor.hpp"
#include "fd_event.hpp"
#include "logger.hpp"
#include "net_address.hpp"
#include <cstring>
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <thread>
using namespace tinyrpc;
using namespace std;

Reactor reactor;

int main() {
    int listenfd = socket(AF_INET, SOCK_STREAM, 0);
    NetAddress na(9001);
    logger() << na.toString();
    int ret = bind(listenfd, na.getSockaddr(), na.getSockLen());
    if(ret == -1) {
        logger() << "bind ret -1 err:" << strerror(errno);
        return -1;
    }

    listen(listenfd, 5);

    FdEvent fe(listenfd);
    fe.addListenEvent(IOEvent::READ);
    fe.setReadCallback([listenfd] {
        thread t([listenfd]{
            sockaddr_in addr;
            socklen_t  len = sizeof addr;
            int fd = accept(listenfd,(sockaddr*)(&addr), &len);

            NetAddress na(&addr);

            FdEvent* cli = new FdEvent(fd);
            cli->addListenEvent(IOEvent::READ);
            cli->setNonblock();
            cli->setReadCallback([fd, cli] {
                char buf[64]{};
                int ret = read(fd, buf, 64);
                if(ret == 0) {
                    
                    reactor.delFdEvent(cli);
                    close(fd);
                    return;
                }

                cout << buf << endl;
                write(fd, buf, ret);
                
            });
            logger() << "addFdEvent" << cli->getFd();
            reactor.addFdEvent(cli);
        }
            
        );

        t.join();
    });
    cout << "listenfd" << listenfd << endl;
    reactor.addFdEvent(&fe);

    reactor.loop();


    
    close(listenfd);

    // enableHook();
    // Reactor* reactor = Reactor::getReactor();
    // char buf[128];
    // read(0, buf, 128);
    // reactor->loop();

}