
// Makes ure gl3w is included before glfw3
#include "GL/gl3w.h"

#define SK_GL
#include "GLFW/glfw3.h"

#include "GrBackendSurface.h"
#include "GrDirectContext.h"
#include "SkCanvas.h"
#include "SkColorSpace.h"
#include "SkSurface.h"
#include "SkTypes.h"
#include "gl/GrGLInterface.h"

#include "rive/animation/linear_animation_instance.hpp"
#include "rive/animation/state_machine_instance.hpp"
#include "rive/animation/state_machine_input_instance.hpp"
#include "rive/animation/state_machine_number.hpp"
#include "rive/animation/state_machine_bool.hpp"
#include "rive/animation/state_machine_trigger.hpp"
#include "rive/artboard.hpp"
#include "rive/file.hpp"
#include "rive/layout.hpp"
#include "rive/math/aabb.hpp"
#include "skia_renderer.hpp"

#include "imgui/backends/imgui_impl_glfw.h"
#include "imgui/backends/imgui_impl_opengl3.h"

#include <cmath>
#include <stdio.h>

std::string filename;
std::unique_ptr<rive::File> currentFile;
std::unique_ptr<rive::Artboard> artboard;
rive::StateMachineInstance* stateMachineInstance = nullptr;
rive::LinearAnimationInstance* animationInstance = nullptr;
uint8_t* fileBytes = nullptr;
unsigned int fileBytesLength = 0;

int animationIndex = 0;
int stateMachineIndex = -1;

void initStateMachine(int index) {
    stateMachineIndex = index;
    animationIndex = -1;
    assert(fileBytes != nullptr);
    auto reader = rive::BinaryReader(fileBytes, fileBytesLength);
    rive::File* file = nullptr;
    auto result = rive::File::import(reader, &file);
    if (result != rive::ImportResult::success) {
        delete[] fileBytes;
        fprintf(stderr, "failed to import file\n");
        return;
    }
    artboard = file->artboard()->instance();
    artboard->advance(0.0f);

    delete animationInstance;
    delete stateMachineInstance;
    animationInstance = nullptr;
    stateMachineInstance = nullptr;

    auto stateMachine = index >= 0 && index < artboard->stateMachineCount()
                            ? artboard->stateMachine(index)
                            : nullptr;
    if (stateMachine != nullptr) {
        stateMachineInstance = new rive::StateMachineInstance(stateMachine);
    }

    currentFile.reset(file);
}

void initAnimation(int index) {
    animationIndex = index;
    stateMachineIndex = -1;
    assert(fileBytes != nullptr);
    auto reader = rive::BinaryReader(fileBytes, fileBytesLength);
    rive::File* file = nullptr;
    auto result = rive::File::import(reader, &file);
    if (result != rive::ImportResult::success) {
        delete[] fileBytes;
        fprintf(stderr, "failed to import file\n");
        return;
    }
    artboard = file->artboard()->instance();
    artboard->advance(0.0f);

    delete animationInstance;
    delete stateMachineInstance;
    animationInstance = nullptr;
    stateMachineInstance = nullptr;

    auto animation =
        index >= 0 && index < artboard->animationCount() ? artboard->animation(index) : nullptr;
    if (animation != nullptr) {
        animationInstance = new rive::LinearAnimationInstance(animation);
    }

    currentFile.reset(file);
}

void glfwErrorCallback(int error, const char* description) { puts(description); }

void glfwDropCallback(GLFWwindow* window, int count, const char** paths) {
    // Just get the last dropped file for now...
    filename = paths[count - 1];

    FILE* fp = fopen(filename.c_str(), "r");
    fseek(fp, 0, SEEK_END);
    fileBytesLength = ftell(fp);
    fseek(fp, 0, SEEK_SET);
    delete[] fileBytes;
    fileBytes = new uint8_t[fileBytesLength];
    if (fread(fileBytes, 1, fileBytesLength, fp) != fileBytesLength) {
        delete[] fileBytes;
        fprintf(stderr, "failed to read all of %s\n", filename.c_str());
        return;
    }
    initAnimation(0);
}

// returns the mouse position, transforming it through the inverse of
// the canvas' CTM -- which may have been altered to scale/translate
// the artboard into the window.
//
static void post_mouse_event(rive::Artboard* artboard, const SkMatrix& ctm) {
    static ImVec2 gPrevMousePos = {-1000, -1000};
    const auto mouse = ImGui::GetMousePos();

    static bool gPrevMouseButtonDown = false;
    const bool isDown = ImGui::IsMouseDown(ImGuiMouseButton_Left);

    if (mouse.x == gPrevMousePos.x &&
        mouse.y == gPrevMousePos.y &&
        isDown == gPrevMouseButtonDown)
    {
        return;
    }
    
    auto evtType = rive::PointerEventType::move;
    if (isDown && !gPrevMouseButtonDown) {
        evtType = rive::PointerEventType::down; // we just went down
    } else if (!isDown && gPrevMouseButtonDown) {
        evtType = rive::PointerEventType::up; // we just went up
    }

    gPrevMousePos = mouse;
    gPrevMouseButtonDown = isDown;

    SkMatrix inv;
    (void)ctm.invert(&inv);
    
    // scale by 2 for the DPI of a high-res monitor
    const auto pt = inv.mapXY(mouse.x * 2, mouse.y * 2);
    
    const int pointerIndex = 0; // til we track more than one button/mouse
    rive::PointerEvent evt = {
        evtType,
        {pt.fX, pt.fY},
        pointerIndex,
    };
    artboard->postPointerEvent(evt);
}

static void test_messages(rive::Artboard* artboard) {
    rive::Message msg;
    int i = 0;
    bool hasAny = artboard->hasMessages();

    while (artboard->nextMessage(&msg)) {
        printf("-- message[%d]: '%s'\n", i, msg.m_Str.c_str());
        i += 1;
    }
    assert((hasAny && i > 0) || (!hasAny && i == 0));
}

int main() {
    if (!glfwInit()) {
        fprintf(stderr, "Failed to initialize glfw.\n");
        return 1;
    }
    glfwSetErrorCallback(glfwErrorCallback);

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    GLFWwindow* window = glfwCreateWindow(1280, 720, "Rive Viewer", NULL, NULL);
    if (window == nullptr) {
        fprintf(stderr, "Failed to make window or GL.\n");
        glfwTerminate();
        return 1;
    }

    glfwSetDropCallback(window, glfwDropCallback);
    glfwMakeContextCurrent(window);
    if (gl3wInit() != 0) {
        fprintf(stderr, "Failed to make initialize gl3w.\n");
        glfwTerminate();
        return 1;
    }
    // Enable VSYNC.
    glfwSwapInterval(1);

    // Setup ImGui
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO();
    (void)io;

    ImGui::StyleColorsDark();
    ImGui_ImplGlfw_InitForOpenGL(window, true);
    ImGui_ImplOpenGL3_Init("#version 150");
    io.Fonts->AddFontDefault();

    // Setup Skia
    GrContextOptions options;
    sk_sp<GrDirectContext> context = GrDirectContext::MakeGL(nullptr, options);
    GrGLFramebufferInfo framebufferInfo;
    framebufferInfo.fFBOID = 0;
    framebufferInfo.fFormat = GL_RGBA8;

    SkSurface* surface = nullptr;
    SkCanvas* canvas = nullptr;

    // Render loop.
    int width = 0, height = 0;
    int lastScreenWidth = 0, lastScreenHeight = 0;
    double lastTime = glfwGetTime();
    while (!glfwWindowShouldClose(window)) {
        glfwGetFramebufferSize(window, &width, &height);

        // Update surface.
        if (surface == nullptr || width != lastScreenWidth || height != lastScreenHeight) {
            lastScreenWidth = width;
            lastScreenHeight = height;

            SkColorType colorType =
                kRGBA_8888_SkColorType; // GrColorTypeToSkColorType(GrPixelConfigToColorType(kRGBA_8888_GrPixelConfig));
            //
            // if (kRGBA_8888_GrPixelConfig == kSkia8888_GrPixelConfig)
            // {
            // 	colorType = kRGBA_8888_SkColorType;
            // }
            // else
            // {
            // 	colorType = kBGRA_8888_SkColorType;
            // }

            GrBackendRenderTarget backendRenderTarget(width,
                                                      height,
                                                      0, // sample count
                                                      0, // stencil bits
                                                      framebufferInfo);

            delete surface;
            surface = SkSurface::MakeFromBackendRenderTarget(context.get(),
                                                             backendRenderTarget,
                                                             kBottomLeft_GrSurfaceOrigin,
                                                             colorType,
                                                             nullptr,
                                                             nullptr)
                          .release();
            if (surface == nullptr) {
                fprintf(stderr, "Failed to create Skia surface\n");
                return 1;
            }
            canvas = surface->getCanvas();
        }

        double time = glfwGetTime();
        float elapsed = (float)(time - lastTime);
        lastTime = time;

        // Clear screen.
        SkPaint paint;
        paint.setColor(SK_ColorDKGRAY);
        canvas->drawPaint(paint);

        if (artboard != nullptr) {
            if (animationInstance != nullptr) {
                animationInstance->advance(elapsed);
                animationInstance->apply(artboard.get());
            } else if (stateMachineInstance != nullptr) {
                stateMachineInstance->advance(artboard.get(), elapsed);
            }
            artboard->advance(elapsed);

            rive::SkiaRenderer renderer(canvas);
            renderer.save();
            renderer.align(rive::Fit::contain,
                           rive::Alignment::center,
                           rive::AABB(0, 0, width, height),
                           artboard->bounds());

            post_mouse_event(artboard.get(), canvas->getTotalMatrix());

            artboard->draw(&renderer);
            renderer.restore();
        }

        context->flush();

        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplGlfw_NewFrame();
        ImGui::NewFrame();

        if (artboard != nullptr) {
            ImGui::Begin(filename.c_str(), nullptr);
            if (ImGui::ListBox(
                    "Animations",
                    &animationIndex,
                    [](void* data, int index, const char** name) {
                        const char* animationName = artboard->animation(index)->name().c_str();
                        *name = animationName;
                        return true;
                    },
                    artboard.get(),
                    artboard->animationCount(),
                    4))
            {
                stateMachineIndex = -1;
                initAnimation(animationIndex);
            }
            if (ImGui::ListBox(
                    "State Machines",
                    &stateMachineIndex,
                    [](void* data, int index, const char** name) {
                        const char* machineName = artboard->stateMachine(index)->name().c_str();
                        *name = machineName;
                        return true;
                    },
                    artboard.get(),
                    artboard->stateMachineCount(),
                    4))
            {
                animationIndex = -1;
                initStateMachine(stateMachineIndex);
            }
            if (stateMachineInstance != nullptr) {

                ImGui::Columns(2);
                ImGui::SetColumnWidth(0, ImGui::GetWindowWidth() * 0.6666);

                for (int i = 0; i < stateMachineInstance->inputCount(); i++) {
                    auto inputInstance = stateMachineInstance->input(i);

                    if (inputInstance->input()->is<rive::StateMachineNumber>()) {
                        // ImGui requires names as id's, use ## to hide the
                        // label but still give it an id.
                        char label[256];
                        snprintf(label, 256, "##%u", i);

                        auto number = static_cast<rive::SMINumber*>(inputInstance);
                        float v = number->value();
                        ImGui::InputFloat(label, &v, 1.0f, 2.0f, "%.3f");
                        number->value(v);
                        ImGui::NextColumn();
                    } else if (inputInstance->input()->is<rive::StateMachineTrigger>()) {
                        // ImGui requires names as id's, use ## to hide the
                        // label but still give it an id.
                        char label[256];
                        snprintf(label, 256, "Fire##%u", i);
                        if (ImGui::Button(label)) {
                            auto trigger = static_cast<rive::SMITrigger*>(inputInstance);
                            trigger->fire();
                        }
                        ImGui::NextColumn();
                    } else if (inputInstance->input()->is<rive::StateMachineBool>()) {
                        // ImGui requires names as id's, use ## to hide the
                        // label but still give it an id.
                        char label[256];
                        snprintf(label, 256, "##%u", i);
                        auto boolInput = static_cast<rive::SMIBool*>(inputInstance);
                        bool value = boolInput->value();

                        ImGui::Checkbox(label, &value);
                        boolInput->value(value);
                        ImGui::NextColumn();
                    }
                    ImGui::Text("%s", inputInstance->input()->name().c_str());
                    ImGui::NextColumn();
                }

                ImGui::Columns(1);
            }
            ImGui::End();
            
            test_messages(artboard.get());
        } else {
            ImGui::Text("Drop a .riv file to preview.");
        }

        ImGui::Render();
        ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    delete[] fileBytes;

    // Cleanup Skia.
    delete surface;
    context = nullptr;

    ImGui_ImplGlfw_Shutdown();

    // Cleanup GLFW.
    glfwDestroyWindow(window);
    glfwTerminate();

    return 0;
}
