
// 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;
rive::File* currentFile = nullptr;
rive::Artboard* artboard = nullptr;
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;
    }
    auto sourceArtboard = file->artboard();
    // Artboard should always be instance and hence must be deleted.
    delete artboard;
    artboard = sourceArtboard->instance();
    artboard->advance(0.0f);

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

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

    currentFile = 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;
    }
    auto sourceArtboard = file->artboard();
    // Artboard should always be instance and hence must be deleted.
    delete artboard;
    artboard = sourceArtboard->instance();
    artboard->advance(0.0f);

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

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

    currentFile = file;
}

rive::Mat2D gInverseViewTransform;
rive::Vec2D lastWorldMouse;
static void glfwCursorPosCallback(GLFWwindow* window, double x, double y) {
    float xscale, yscale;
    glfwGetWindowContentScale(window, &xscale, &yscale);
    lastWorldMouse = gInverseViewTransform * rive::Vec2D(x * xscale, y * yscale);
    if (stateMachineInstance != nullptr) {
        stateMachineInstance->pointerMove(lastWorldMouse);
    }
}
void glfwMouseButtonCallback(GLFWwindow* window, int button, int action, int mods) {
    if (stateMachineInstance != nullptr) {
        switch (action) {
            case GLFW_PRESS:
                stateMachineInstance->pointerDown(lastWorldMouse);
                break;
            case GLFW_RELEASE:
                stateMachineInstance->pointerUp(lastWorldMouse);
                break;
        }
    }
}

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);
    glfwSetCursorPosCallback(window, glfwCursorPosCallback);
    glfwSetMouseButtonCallback(window, glfwMouseButtonCallback);
    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);
            } else if (stateMachineInstance != nullptr) {
                stateMachineInstance->advance(elapsed);
            }
            artboard->advance(elapsed);

            rive::SkiaRenderer renderer(canvas);
            renderer.save();
            rive::Mat2D viewTransform;
            renderer.computeAlignment(viewTransform,
                                      rive::Fit::contain,
                                      rive::Alignment::center,
                                      rive::AABB(0, 0, width, height),
                                      artboard->bounds());
            renderer.transform(viewTransform);
            // Store the inverse view so we can later go from screen to world.
            rive::Mat2D::invert(gInverseViewTransform, viewTransform);
            // post_mouse_event(artboard, 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,
                    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,
                    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);
        } else {
            ImGui::Text("Drop a .riv file to preview.");
        }

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

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    delete currentFile;
    delete[] fileBytes;

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

    ImGui_ImplGlfw_Shutdown();

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

    return 0;
}
