/*
 *
 *    Copyright (c) 2023 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 "ui.h"

#include <SDL.h>
#include <SDL_opengl.h>
#include <imgui.h>
#include <imgui_impl_opengl3.h>
#include <imgui_impl_sdl2.h>

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

#include <atomic>
#include <thread>

namespace example {
namespace Ui {
namespace {

// Controls running the UI event loop
std::atomic<bool> gUiRunning{ false };

void UiInit(SDL_GLContext * gl_context, SDL_Window ** window)
{
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
    {
        ChipLogError(AppServer, "SDL Init Error: %s\n", SDL_GetError());
        return;
    }

#if defined(__APPLE__)
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
#else
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
#endif

#ifdef SDL_HINT_IME_SHOW_UI
    SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
#endif

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
    SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
    SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
    *window     = SDL_CreateWindow("Light UI", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
    *gl_context = SDL_GL_CreateContext(*window);
    SDL_GL_MakeCurrent(*window, *gl_context);
    SDL_GL_SetSwapInterval(1); // Enable vsync

    // Setup Dear ImGui context
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO & io = ImGui::GetIO();
    (void) io;
    // io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
    // io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls

    ImGui::StyleColorsDark();

    // Setup Platform/Renderer backends
    ImGui_ImplSDL2_InitForOpenGL(*window, *gl_context);
    ImGui_ImplOpenGL3_Init();
}

void UiShutdown(SDL_GLContext * gl_context, SDL_Window ** window)
{
    ImGui_ImplOpenGL3_Shutdown();
    ImGui_ImplSDL2_Shutdown();
    ImGui::DestroyContext();

    SDL_GL_DeleteContext(*gl_context);
    SDL_DestroyWindow(*window);
    SDL_Quit();
}

void EventLoop(ImguiUi * ui)
{
    gUiRunning = true;
    SDL_GLContext gl_context;
    SDL_Window * window = nullptr;

    UiInit(&gl_context, &window);

    ImGuiIO & io = ImGui::GetIO();

    while (gUiRunning.load())
    {
        SDL_Event event;
        while (SDL_PollEvent(&event))
        {
            ImGui_ImplSDL2_ProcessEvent(&event);
            if ((event.type == SDL_QUIT) ||
                (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE &&
                 event.window.windowID == SDL_GetWindowID(window)))
            {
                gUiRunning = false;
            }
        }

        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplSDL2_NewFrame();
        ImGui::NewFrame();

        ui->UpdateState();
        ui->Render();

        // rendering
        ImGui::Render();
        glViewport(0, 0, (int) io.DisplaySize.x, (int) io.DisplaySize.y);
        glClearColor(0, 0, 0, 0);
        glClear(GL_COLOR_BUFFER_BIT);
        ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
        SDL_GL_SwapWindow(window);
    }

    UiShutdown(&gl_context, &window);

    ChipLogProgress(AppServer, "UI thread Stopped...");
}

} // namespace

void ImguiUi::RunMainLoop()
{
    // Guaranteed to be on the main task (no chip event loop started yet)
    ChipLoopLoadInitialState();

    // Platform event loop will be on a separate thread,
    // while the event UI loop will be on the main thread.
    chip::DeviceLayer::PlatformMgr().StartEventLoopTask();

    // SignalSafeStopMainLoop will stop this loop below
    // or the loop exits by itself when processing a SDL
    // exit (generally by clicking the window close icon).
    EventLoop(this);

    // ensure shutdown events are generated (generally basic cluster
    // will send a shutdown event to subscribers).
    //
    // We attempt to wait for finish as the event will be sent sync.
    // Since the Main loop is stopped, there will be no MRP, however at least
    // one event is attempted to be sent.
    chip::DeviceLayer::PlatformMgr().ScheduleWork(
        [](intptr_t arg) {
            chip::DeviceLayer::PlatformMgr().HandleServerShuttingDown();
            sem_t * semaphore = reinterpret_cast<sem_t *>(arg);
            sem_post(semaphore); // notify complete
        },
        reinterpret_cast<intptr_t>(&mChipLoopWaitSemaphore));
    sem_wait(&mChipLoopWaitSemaphore);

    // Stop the chip main loop as well. This is expected to
    // wait for the task to finish.
    chip::DeviceLayer::PlatformMgr().StopEventLoopTask();
}

void ImguiUi::SignalSafeStopMainLoop()
{
    gUiRunning = false;
}

void ImguiUi::ChipLoopStateUpdate()
{
    assertChipStackLockedByCurrentThread();
    for (auto it = mWindows.begin(); it != mWindows.end(); it++)
    {
        (*it)->UpdateState();
    }
}

void ImguiUi::ChipLoopLoadInitialState()
{
    assertChipStackLockedByCurrentThread();
    for (auto it = mWindows.begin(); it != mWindows.end(); it++)
    {
        (*it)->LoadInitialState();
    }
}

void ImguiUi::Render()
{
    for (auto it = mWindows.begin(); it != mWindows.end(); it++)
    {
        (*it)->Render();
    }
}

void ImguiUi::ChipLoopUpdateCallback(intptr_t self)
{
    ImguiUi * _this = reinterpret_cast<ImguiUi *>(self);
    _this->ChipLoopStateUpdate();
    sem_post(&_this->mChipLoopWaitSemaphore); // notify complete
}

void ImguiUi::UpdateState()
{
    CHIP_ERROR err = chip::DeviceLayer::PlatformMgr().ScheduleWork(&ChipLoopUpdateCallback, reinterpret_cast<intptr_t>(this));

    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(AppServer, "Failed to schedule state update: %" CHIP_ERROR_FORMAT, err.Format());
        return;
    }

    // ensure update is done when exiting
    sem_wait(&mChipLoopWaitSemaphore);
}

} // namespace Ui
} // namespace example
