/*
 *    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.
 */

#include "MainLoop.h"

#include <iterator>
#include <memory>
#include <utility>

#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>

namespace chip {
namespace DeviceLayer {
namespace Internal {

LoopData::LoopData()
{
    mMainContext = g_main_context_new();
    mMainLoop    = g_main_loop_new(mMainContext, FALSE);
}

LoopData::~LoopData()
{
    if (mThread.joinable())
    {
        mThread.join();
    }
    if (mMainContext != nullptr)
    {
        g_main_context_unref(mMainContext);
    }
    if (mMainLoop != nullptr)
    {
        g_main_loop_unref(mMainLoop);
    }
}

gboolean MainLoop::ThreadTimeout(gpointer userData)
{
    LoopData * loopData = reinterpret_cast<LoopData *>(userData);

    VerifyOrReturnError(loopData != nullptr, G_SOURCE_REMOVE);

    ChipLogDetail(DeviceLayer, "[TIMEOUT] glib main loop [%p]", loopData->mMainLoop);

    if (loopData->mTimeoutFn)
    {
        ChipLogDetail(DeviceLayer, "Running thread timeout function");
        loopData->mTimeoutFn(loopData->mTimeoutUserData);
    }

    g_main_loop_quit(loopData->mMainLoop);

    return G_SOURCE_REMOVE;
}

void MainLoop::ThreadHandler(std::shared_ptr<LoopData> loopData)
{
    g_main_context_push_thread_default(loopData->mMainContext);
    ChipLogDetail(DeviceLayer, "[PUSH] thread default context [%p]", loopData->mMainContext);

    ChipLogDetail(DeviceLayer, "[RUN] glib main loop [%p]", loopData->mMainLoop);
    g_main_loop_run(loopData->mMainLoop);
    ChipLogDetail(DeviceLayer, "[QUIT] glib main loop [%p]", loopData->mMainLoop);

    g_main_context_pop_thread_default(loopData->mMainContext);
    ChipLogDetail(DeviceLayer, "[POP] thread default context [%p]", loopData->mMainContext);
}

bool MainLoop::Init(initFn_t initFn, gpointer userData)
{
    auto loopData = std::make_shared<LoopData>();
    bool result   = false;

    VerifyOrReturnError(loopData, false);

    g_main_context_push_thread_default(loopData->mMainContext);
    ChipLogDetail(DeviceLayer, "[PUSH] thread default context [%p]", loopData->mMainContext);

    result = initFn(userData);

    g_main_context_pop_thread_default(loopData->mMainContext);
    ChipLogDetail(DeviceLayer, "[POP] thread default context [%p]", loopData->mMainContext);

    VerifyOrReturnError(result, false);

    loopData->mThread = std::thread(ThreadHandler, loopData);
    mLoopData.push_back(loopData);

    return true;
}

void MainLoop::Deinit()
{
    for (auto & loopData : mLoopData)
    {
        g_main_loop_quit(loopData->mMainLoop);
    }
    mLoopData.clear();
}

bool MainLoop::AsyncRequest(asyncFn_t asyncFn, gpointer asyncUserData, guint timeoutInterval, timeoutFn_t timeoutFn,
                            gpointer timeoutUserData)
{
    auto loopData = std::make_shared<LoopData>();
    bool result   = false;

    VerifyOrReturnError(loopData, false);

    loopData->mTimeoutFn       = timeoutFn;
    loopData->mTimeoutUserData = timeoutUserData;

    g_main_context_push_thread_default(loopData->mMainContext);
    ChipLogDetail(DeviceLayer, "[PUSH] thread default context [%p]", loopData->mMainContext);

    result = asyncFn(loopData->mMainLoop, asyncUserData);

    g_main_context_pop_thread_default(loopData->mMainContext);
    ChipLogDetail(DeviceLayer, "[POP] thread default context [%p]", loopData->mMainContext);

    VerifyOrReturnError(result, false);

    loopData->mThread = std::thread(ThreadHandler, loopData);
    loopData->mThread.detach();

    if (timeoutInterval)
    {
        GSource * source = g_timeout_source_new_seconds(timeoutInterval);
        g_source_set_callback(source, ThreadTimeout, loopData.get(), nullptr);
        g_source_attach(source, loopData->mMainContext);
        g_source_unref(source);
    }

    return true;
}

MainLoop & MainLoop::Instance()
{
    static MainLoop sMainLoop;
    return sMainLoop;
}

} // namespace Internal
} // namespace DeviceLayer
} // namespace chip
