#include "io_thread.hpp"
#include "logger.hpp"
#include "reactor.hpp"
#include "coroutine.hpp"
#include "server_tcp_connect.hpp"
#include "tcp_server.hpp"
#include <memory>
#include <mutex>
#include <thread>


namespace tinyrpc {
    static thread_local Reactor* t_reactor = nullptr;
    static thread_local IOThread* t_ioThread = nullptr;


    // static IOThread* getThisIoThread() {
    //     return t_ioThread;
    // }

    IOThread::IOThread() : m_thread(&IOThread::mainFunc, this) {
        logger() << "IO Thread is built";
    }



    void IOThread::addClient(TcpServer* ser, int fd) {
     
        m_clients[fd] = std::shared_ptr<ServerTcpConnection>(new ServerTcpConnection(fd, *m_reactor, *ser));

    }

    void IOThread::mainFunc() {
        if(t_ioThread) {
            logger() << "this thread already built!";
            exit(-1);
        }

        if(t_reactor) {
            logger() << "this thread:" << std::this_thread::get_id() << " already has reactor!";
            exit(-1);
        }
        
        t_ioThread = this;
        m_reactor = t_reactor = new Reactor(Reactor::ReactorType::Sub);
        Coroutine::getMainCoroutine(); // 创建协程
        m_reactor->loop();
    }

    IOThread::~IOThread() {
        m_reactor->stop();
        if(m_thread.joinable()) {
            m_thread.join();
        }
        delete m_reactor;
        t_reactor = nullptr;
        t_ioThread = nullptr;

    }

    IOThreadPool::IOThreadPool(int size) : m_IOThreads(size, new IOThread){

    }

    IOThread* IOThreadPool::getIOThread() {
        
        std::lock_guard<std::mutex> lock(m_mtx);
        if(m_idx == static_cast<int>(m_IOThreads.size() - 1)) {
            m_idx = -1;
        }
        return m_IOThreads[++m_idx];

    }

    IOThreadPool::~IOThreadPool() {
        for(auto item : m_IOThreads) {
            delete item;
        }
    }
}