/*
 *
 *    Copyright (c) 2021 Project CHIP Authors
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

/**
 *    @file
 *      This file implements System::Layer using libevent.
 */

#include <lib/support/CodeUtils.h>
#include <platform/CHIPDeviceBuildConfig.h>
#include <system/SystemFaultInjection.h>
#include <system/SystemLayer.h>
#include <system/SystemLayerImplLibevent.h>

#include <algorithm>
#include <fcntl.h>
#include <unistd.h>

#ifndef CHIP_CONFIG_LIBEVENT_DEBUG_CHECKS
#define CHIP_CONFIG_LIBEVENT_DEBUG_CHECKS 1
#endif

// Choose an approximation of PTHREAD_NULL if pthread.h doesn't define one.
#if CHIP_SYSTEM_CONFIG_POSIX_LOCKING && !defined(PTHREAD_NULL)
#define PTHREAD_NULL 0
#endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING && !defined(PTHREAD_NULL)

namespace chip {
namespace System {

namespace {

System::SocketEvents SocketEventsFromLibeventFlags(short eventFlags)
{
    return System::SocketEvents()
        .Set(SocketEventFlags::kRead, eventFlags & EV_READ)
        .Set(SocketEventFlags::kWrite, eventFlags & EV_WRITE);
}

} // anonymous namespace

CHIP_ERROR LayerImplLibevent::Init(System::Layer & systemLayer)
{
    VerifyOrReturnError(mLayerState.SetInitializing(), CHIP_ERROR_INCORRECT_STATE);

    RegisterPOSIXErrorFormatter();

#if CHIP_CONFIG_LIBEVENT_DEBUG_CHECKS
    static bool enabled_event_debug_mode = false;
    if (!enabled_event_debug_mode)
    {
        enabled_event_debug_mode = true;
        event_enable_debug_mode();
    }
#endif // CHIP_CONFIG_LIBEVENT_DEBUG_CHECKS

    mSystemLayer = &systemLayer;
    mEventBase   = event_base_new();
    VerifyOrReturnError(mEventBase != nullptr, CHIP_ERROR_NO_MEMORY);

#if CHIP_DEVICE_CONFIG_ENABLE_DNSSD && !__ZEPHYR__
    mMdnsTimeoutEvent = evtimer_new(mEventBase, MdnsTimeoutCallbackHandler, this);
    VerifyOrReturnError(mMdnsTimeoutEvent != nullptr, CHIP_ERROR_NO_MEMORY);
#endif // CHIP_DEVICE_CONFIG_ENABLE_DNSSD && !__ZEPHYR__

#if CHIP_SYSTEM_CONFIG_POSIX_LOCKING
    mHandleSelectThread = PTHREAD_NULL;
#endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING

    Mutex::Init(mTimerListMutex);

    VerifyOrReturnError(mLayerState.SetInitialized(), CHIP_ERROR_INCORRECT_STATE);
    return CHIP_NO_ERROR;
}

#if CHIP_DEVICE_CONFIG_ENABLE_DNSSD && !__ZEPHYR__

// static
void LayerImplLibevent::MdnsTimeoutCallbackHandler(evutil_socket_t fd, short eventFlags, void * data)
{
    reinterpret_cast<LayerImplLibevent *>(data)->MdnsTimeoutCallbackHandler();
}

void LayerImplLibevent::MdnsTimeoutCallbackHandler()
{
#if CHIP_SYSTEM_CONFIG_POSIX_LOCKING
    mHandleSelectThread = pthread_self();
#endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING

    chip::Dnssd::HandleMdnsTimeout();

#if CHIP_SYSTEM_CONFIG_POSIX_LOCKING
    mHandleSelectThread = PTHREAD_NULL;
#endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING
}
#endif // CHIP_DEVICE_CONFIG_ENABLE_DNSSD && !__ZEPHYR__

CHIP_ERROR LayerImplLibevent::Shutdown()
{
    VerifyOrReturnError(mLayerState.SetShuttingDown(), CHIP_ERROR_INCORRECT_STATE);

    event_base_loopbreak(mEventBase);

#if CHIP_DEVICE_CONFIG_ENABLE_DNSSD && !__ZEPHYR__
    if (mMdnsTimeoutEvent != nullptr)
    {
        event_free(mMdnsTimeoutEvent);
        mMdnsTimeoutEvent = nullptr;
    }
#endif // CHIP_DEVICE_CONFIG_ENABLE_DNSSD && !__ZEPHYR__

    mTimerListMutex.Lock();
    mTimers.clear();
    mTimerListMutex.Unlock();

    mSocketWatches.clear();

    event_base_free(mEventBase);
    mEventBase   = nullptr;
    mSystemLayer = nullptr;

    mLayerState.SetShutdown();
    mLayerState.Reset(); // Return to uninitialized state to permit re-initialization.
    return CHIP_NO_ERROR;
}

void LayerImplLibevent::Signal()
{
    /*
     * Wake up the I/O thread by writing a single byte to the wake pipe.
     *
     * If this is being called from within an I/O event callback, then writing to the wake pipe can be skipped,
     * since the I/O thread is already awake.
     *
     * Furthermore, we don't care if this write fails as the only reasonably likely failure is that the pipe is full, in which
     * case the select calling thread is going to wake up anyway.
     */
#if CHIP_SYSTEM_CONFIG_POSIX_LOCKING
    if (pthread_equal(mHandleSelectThread, pthread_self()))
    {
        return;
    }
#endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING

    // Send notification to wake up the select call.
    CHIP_ERROR status = mWakeEvent.Notify();
    if (status != CHIP_NO_ERROR)
    {
        ChipLogError(chipSystemLayer, "System wake event notify failed: %" CHIP_ERROR_FORMAT, status.Format());
    }
}

CHIP_ERROR LayerImplLibevent::StartTimer(Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState)
{
    VerifyOrReturnError(mLayerState.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);

    std::lock_guard<Mutex> lock(mTimerListMutex);
    mTimers.push_back(std::make_unique<LibeventTimer>(this, onComplete, appState));
    LibeventTimer * timer = mTimers.back().get();
    if (timer == nullptr)
    {
        mTimers.pop_back();
        return CHIP_ERROR_NO_MEMORY;
    }

    event * e = evtimer_new(mEventBase, TimerCallbackHandler, timer);
    VerifyOrReturnError(e != nullptr, CHIP_ERROR_NO_MEMORY);
    timer->mEvent = e;

    timeval tv;
    Clock::ToTimeval(delay, tv);
    int status = evtimer_add(e, &tv);
    VerifyOrReturnError(status == 0, CHIP_ERROR_INTERNAL);

    return CHIP_NO_ERROR;
}

void LayerImplLibevent::CancelTimer(TimerCompleteCallback onComplete, void * appState)
{
    VerifyOrReturnError(mLayerState.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);

    std::lock_guard<Mutex> lock(mTimerListMutex);
    auto it = std::find_if(mTimers.begin(), mTimers.end(), [onComplete, appState](const std::unique_ptr<LibeventTimer> & timer) {
        return timer->mOnComplete == onComplete && timer->mCallbackData == appState;
    });
    if (it != mTimers.end())
    {
        LibeventTimer * timer = it->get();
        mActiveTimers.remove(timer);
        mTimers.remove_if([timer](const std::unique_ptr<LibeventTimer> & t) { return t.get() == timer; });
    }
}

CHIP_ERROR LayerImplLibevent::ScheduleWork(TimerCompleteCallback onComplete, void * appState)
{
    assertChipStackLockedByCurrentThread();
    VerifyOrReturnError(mLayerState.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);

    return StartTimer(Clock::Zero, onComplete, appState);
}

// static
void LayerImplLibevent::TimerCallbackHandler(evutil_socket_t fd, short eventFlags, void * data)
{
    // Copy the necessary timer information and remove it from the list.
    LibeventTimer * timer            = reinterpret_cast<LibeventTimer *>(data);
    Layer * systemLayer              = timer->mEventManager->mSystemLayer;
    TimerCompleteCallback onComplete = timer->mOnComplete;
    void * callbackData              = timer->mCallbackData;
    systemLayer->CancelTimer(onComplete, callbackData);
    if (onComplete)
    {
        onComplete(systemLayer, callbackData);
    }
}

LayerImplLibevent::LibeventTimer::~LibeventTimer()
{
    mEventManager = nullptr;
    mOnComplete   = nullptr;
    mCallbackData = nullptr;
    if (mEvent)
    {
        if (evtimer_pending(mEvent, nullptr))
        {
            event_del(mEvent);
        }
        event_free(mEvent);
        mEvent = nullptr;
    }
};

CHIP_ERROR LayerImplLibevent::StartWatchingSocket(int fd, SocketWatchToken * tokenOut)
{
    mSocketWatches.push_back(std::make_unique<SocketWatch>(this, fd));
    SocketWatch * watch = mSocketWatches.back().get();
    if (watch == nullptr)
    {
        mSocketWatches.pop_back();
        return CHIP_ERROR_NO_MEMORY;
    }

    *tokenOut = reinterpret_cast<SocketWatchToken>(watch);
    return CHIP_NO_ERROR;
}

CHIP_ERROR LayerImplLibevent::SetCallback(SocketWatchToken token, SocketWatchCallback callback, intptr_t data)
{
    SocketWatch * watch = reinterpret_cast<SocketWatch *>(token);
    VerifyOrReturnError(watch != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

    watch->mCallback     = callback;
    watch->mCallbackData = data;
    return CHIP_NO_ERROR;
}

CHIP_ERROR LayerImplLibevent::RequestCallbackOnPendingRead(SocketWatchToken token)
{
    return SetWatch(token, EV_READ);
}

CHIP_ERROR LayerImplLibevent::RequestCallbackOnPendingWrite(SocketWatchToken token)
{
    return SetWatch(token, EV_WRITE);
}

CHIP_ERROR LayerImplLibevent::ClearCallbackOnPendingRead(SocketWatchToken token)
{
    return ClearWatch(token, EV_READ);
}

CHIP_ERROR LayerImplLibevent::ClearCallbackOnPendingWrite(SocketWatchToken token)
{
    return ClearWatch(token, EV_WRITE);
}

CHIP_ERROR LayerImplLibevent::StopWatchingSocket(SocketWatchToken * tokenInOut)
{
    SocketWatch * watch = reinterpret_cast<SocketWatch *>(*tokenInOut);
    VerifyOrReturnError(watch != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    *tokenInOut = InvalidSocketWatchToken();

    mActiveSocketWatches.remove(watch);
    mSocketWatches.remove_if([watch](const std::unique_ptr<SocketWatch> & w) { return w.get() == watch; });
    return CHIP_NO_ERROR;
}

SocketWatchToken InvalidSocketWatchToken()
{
    return reinterpret_cast<SocketWatchToken>(nullptr);
}

CHIP_ERROR LayerImplLibevent::SetWatch(SocketWatchToken token, short eventFlags)
{
    SocketWatch * watch = reinterpret_cast<SocketWatch *>(token);
    VerifyOrReturnError(watch != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

    const short oldFlags = watch->mEvent ? event_get_events(watch->mEvent) : 0;
    return UpdateWatch(watch, static_cast<short>(EV_PERSIST | oldFlags | eventFlags));
}

CHIP_ERROR LayerImplLibevent::ClearWatch(SocketWatchToken token, short eventFlags)
{
    SocketWatch * watch = reinterpret_cast<SocketWatch *>(token);
    VerifyOrReturnError(watch != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

    const short oldFlags = watch->mEvent ? event_get_events(watch->mEvent) : 0;
    return UpdateWatch(watch, static_cast<short>(EV_PERSIST | (oldFlags & ~eventFlags)));
}

CHIP_ERROR LayerImplLibevent::UpdateWatch(SocketWatch * watch, short eventFlags)
{
    if (watch->mEvent != nullptr)
    {
        if (event_get_events(watch->mEvent) == eventFlags)
        {
            // No update needed.
            return CHIP_NO_ERROR;
        }
        if (event_pending(watch->mEvent, EV_TIMEOUT | EV_READ | EV_WRITE | EV_SIGNAL, nullptr))
        {
            event_del(watch->mEvent);
        }
        event_free(watch->mEvent);
        watch->mEvent = nullptr;
    }

    if (eventFlags)
    {
        // libevent requires the socket to already be non-blocking.
        int flags = ::fcntl(watch->mFD, F_GETFL, 0);
        if ((flags & O_NONBLOCK) == 0)
        {
            int status = ::fcntl(watch->mFD, F_SETFL, flags | O_NONBLOCK);
            VerifyOrReturnError(status == 0, CHIP_ERROR_POSIX(errno));
        }
        watch->mEvent = event_new(mEventBase, watch->mFD, eventFlags, SocketCallbackHandler, watch);
        VerifyOrReturnError(watch->mEvent != nullptr, CHIP_ERROR_NO_MEMORY);
        int status = event_add(watch->mEvent, nullptr);
        VerifyOrReturnError(status == 0, CHIP_ERROR_INTERNAL);
    }

    return CHIP_NO_ERROR;
}

// static
void LayerImplLibevent::SocketCallbackHandler(evutil_socket_t fd, short eventFlags, void * data)
{
    SocketWatch * const watch = reinterpret_cast<SocketWatch *>(data);
    VerifyOrDie(watch != nullptr);
    VerifyOrDie(watch->mFD == fd);

    watch->mPendingIO = SocketEventsFromLibeventFlags(eventFlags);
    watch->mEventManager->mActiveSocketWatches.push_back(watch);
}

LayerImplLibevent::SocketWatch::~SocketWatch()
{
    mEventManager = nullptr;
    mFD           = kInvalidFd;
    mCallback     = nullptr;
    mCallbackData = 0;
    if (mEvent)
    {
        if (event_pending(mEvent, EV_TIMEOUT | EV_READ | EV_WRITE | EV_SIGNAL, nullptr))
        {
            event_del(mEvent);
        }
        event_free(mEvent);
        mEvent = nullptr;
    }
}

void LayerImplLibevent::PrepareEvents()
{
#if CHIP_DEVICE_CONFIG_ENABLE_DNSSD && !__ZEPHYR__ && !__MBED__
    timeval mdnsTimeout = { 0, 0 };
    chip::Dnssd::GetMdnsTimeout(mdnsTimeout);
    if (mdnsTimeout.tv_sec || mdnsTimeout.tv_usec)
    {
        evtimer_add(mMdnsTimeoutEvent, &mdnsTimeout);
    }
#endif // CHIP_DEVICE_CONFIG_ENABLE_DNSSD && !__ZEPHYR__
}

void LayerImplLibevent::WaitForEvents()
{
    VerifyOrDie(mEventBase != nullptr);
    event_base_loop(mEventBase, EVLOOP_ONCE);
}

void LayerImplLibevent::HandleEvents()
{
#if CHIP_SYSTEM_CONFIG_POSIX_LOCKING
    mHandleSelectThread = pthread_self();
#endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING

    while (!mActiveSocketWatches.empty())
    {
        SocketWatch * const watch = mActiveSocketWatches.front();
        mActiveSocketWatches.pop_front();
        if (watch->mPendingIO.HasAny() && watch->mCallback != nullptr)
        {
            watch->mCallback(watch->mPendingIO, watch->mCallbackData);
        }
    }

#if CHIP_SYSTEM_CONFIG_POSIX_LOCKING
    mHandleSelectThread = PTHREAD_NULL;
#endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING
}

} // namespace System
} // namespace chip
