/**
 *
 *  Channel.cc
 *  An Tao
 *
 *  Public header file in trantor lib.
 *
 *  Copyright 2018, An Tao.  All rights reserved.
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the License file.
 *
 *
 */

#include "Channel.h"
#include <trantor/net/EventLoop.h>
#ifdef _WIN32
#include "Wepoll.h"
#define POLLIN EPOLLIN
#define POLLPRI EPOLLPRI
#define POLLOUT EPOLLOUT
#define POLLHUP EPOLLHUP
#define POLLNVAL 0
#define POLLERR EPOLLERR
#else
#include <poll.h>
#endif
#include <iostream>
namespace trantor
{
const int Channel::kNoneEvent = 0;

const int Channel::kReadEvent = POLLIN | POLLPRI;
const int Channel::kWriteEvent = POLLOUT;

Channel::Channel(EventLoop *loop, int fd)
    : loop_(loop), fd_(fd), events_(0), revents_(0), index_(-1), tied_(false)
{
}

void Channel::remove()
{
    assert(events_ == kNoneEvent);
    addedToLoop_ = false;
    loop_->removeChannel(this);
}

void Channel::update()
{
    loop_->updateChannel(this);
}

void Channel::handleEvent()
{
    // LOG_TRACE<<"revents_="<<revents_;
    if (events_ == kNoneEvent)
        return;
    if (tied_)
    {
        std::shared_ptr<void> guard = tie_.lock();
        if (guard)
        {
            handleEventSafely();
        }
    }
    else
    {
        handleEventSafely();
    }
}
void Channel::handleEventSafely()
{
    if (eventCallback_)
    {
        eventCallback_();
        return;
    }
    if ((revents_ & POLLHUP) && !(revents_ & POLLIN))
    {
        // LOG_TRACE<<"handle close";
        if (closeCallback_)
            closeCallback_();
    }
    if (revents_ & (POLLNVAL | POLLERR))
    {
        // LOG_TRACE<<"handle error";
        if (errorCallback_)
            errorCallback_();
    }
#ifdef __linux__
    if (revents_ & (POLLIN | POLLPRI | POLLRDHUP))
#else
    if (revents_ & (POLLIN | POLLPRI))
#endif
    {
        // LOG_TRACE<<"handle read";
        if (readCallback_)
            readCallback_();
    }
#ifdef _WIN32
    if ((revents_ & POLLOUT) && !(revents_ & POLLHUP))
#else
    if (revents_ & POLLOUT)
#endif
    {
        // LOG_TRACE<<"handle write";
        if (writeCallback_)
            writeCallback_();
    }
}

}  // namespace trantor
