
#include <sys/epoll.h>
#include "ZWForwardEpoll.h"


namespace mfs
{
    ZWForwardEpoll* ZWForwardEpoll::_instance = new ZWForwardEpoll();
    int ZWForwardEpoll::run(int count)
    {
        if (_running)
        {
            return 0;
        }
        _running = true;

        for (size_t i = 0; i < count; i++)
        {
            ZWEpollThreadContext context;
            context.epollfd = epoll_create(1);
            if (context.epollfd<=0)
            {
                LOG_ERROR << "Failted to create epoll!" << LOG_ENDL;
                return -1;
            }
            
            _contexts.push_back(context);
        }
        
        for (size_t i = 0; i < count; i++)
        {
            std::thread(&ZWForwardEpoll::runInner, this, &_contexts[i]).detach();
        }
        return 0;
    }
    void ZWForwardEpoll::add(int fd, std::function<void(int)> func)
    {
        std::vector<int>::iterator iter = std::find(_fds.begin(), _fds.end(), fd);
        if (iter != _fds.end())
        {
            LOG_ERROR <<"Repeat add fd! "<<fd <<LOG_ENDL;
            return;
        }
        else
        {
            int minCount = _contexts[0].readfds.size();
            int minIndex = 0;
            for (int i = 1; i < _contexts.size(); i++)
            {
                if (_contexts[i].readfds.size() < minCount)
                {
                    minCount = _contexts[i].readfds.size();
                    minIndex = i;
                }
            }

            epoll_event event;
            event.events = EPOLLIN;
            event.data.fd = fd;
            auto iret = epoll_ctl(_contexts[minIndex].epollfd, EPOLL_CTL_ADD, fd, &event);
            if (iret == 0)
            {
                ZWEpollContent content;
                content.fd = fd;
                content.event = event;
                content.readfunc = func;
                _contexts[minIndex].readfds.insert(std::pair<int, ZWEpollContent>(fd, content));
                _fds.push_back(fd);
                LOG_DEBUG << "PUSH FD="<<fd<< LOG_ENDL;
            }
            else
            {
                LOG_ERROR << "error epoll_ctl" << LOG_ENDL;
            }

            

            
        }
    }
    void ZWForwardEpoll::remove(int fd)
    {
        for (int i = 0; i < _contexts.size(); i++)
        {
            auto iter = _contexts[i].readfds.find(fd);
            if (iter != _contexts[i].readfds.end())
            {
                LOG_DEBUG << "ERASE FD="<<fd<< LOG_ENDL;
                _contexts[i].readfds.erase(iter);
                break;
            }
        }
    }                 

    void ZWForwardEpoll::runInner(ZWEpollThreadContext*context)
    {
        epoll_event* events = (epoll_event*)malloc(sizeof(epoll_event)*1000);

        while (!_abort)
        {
            auto eventCount = epoll_wait(context->epollfd, events, 1000, 250);
            if (eventCount<=0)
            {
                continue;
            }
            for (int i = 0; i < eventCount; i++)
            {
                if (events[i].events & EPOLLIN)
                {
                    context->readfds[events[i].data.fd].readfunc(events[i].data.fd);
                }
            }
        }
        _running = false;
    }
    
    int write(int fd, const char* buf, int length)
    {
        return 0;
    }
}
