/*
 * Copyright 2022 Rive
 */

#include "rive/artboard.hpp"
#include "rive/file.hpp"
#include "rive/refcnt.hpp"
#include "rive/animation/linear_animation_instance.hpp"
#include "rive/animation/state_machine_instance.hpp"
#include "rive/animation/state_machine_input_instance.hpp"
#include "utils/no_op_factory.hpp"

class JSoner
{
    std::vector<bool> m_IsArray;

    void tab()
    {
        for (int i = 0; i < m_IsArray.size(); ++i)
        {
            printf("\t");
        }
    }
    void add_c(const char key[], char c)
    {
        this->tab();
        if (key)
        {
            printf("\"%s\": %c\n", key, c);
        }
        else
        {
            printf("%c\n", c);
        }
    }

public:
    JSoner() {}
    ~JSoner()
    {
        while (!m_IsArray.empty())
        {
            this->pop();
        }
    }

    void add(const char key[], const char value[])
    {
        this->tab();
        printf("\"%s\": \"%s\"\n", key, value);
    }
    void pushArray(const char key[] = nullptr)
    {
        this->add_c(key, '[');
        m_IsArray.push_back(true);
    }
    void pushStruct(const char key[] = nullptr)
    {
        this->add_c(key, '{');
        m_IsArray.push_back(false);
    }
    void pop()
    {
        assert(!m_IsArray.empty());
        char c = m_IsArray.front() ? ']' : '}';
        m_IsArray.pop_back();

        this->tab();
        printf("%c\n", c);
    }

    void add(const char key[], int value)
    {
        this->add(key, std::to_string(value).c_str());
    }
};

//////////////////////////////////////////////////

static void dump(JSoner& js, rive::LinearAnimationInstance* anim)
{
    js.pushStruct();
    js.add("name", anim->name().c_str());
    js.add("duration", std::to_string(anim->durationSeconds()).c_str());
    js.add("loop", std::to_string(anim->loopValue()).c_str());
    js.pop();
}

static void dump(JSoner& js, rive::StateMachineInstance* smi)
{
    js.pushStruct();
    js.add("name", smi->name().c_str());
    if (auto count = smi->inputCount())
    {
        js.pushArray("inputs");
        for (auto i = 0; i < count; ++i)
        {
            auto inp = smi->input(i);
            js.add("name", inp->name().c_str());
        }
        js.pop();
    }
    js.pop();
}

static void dump(JSoner& js, rive::ArtboardInstance* abi)
{
    js.pushStruct();
    js.add("name", abi->name().c_str());
    if (auto count = abi->animationCount())
    {
        js.pushArray("animations");
        for (size_t i = 0; i < count; ++i)
        {
            dump(js, abi->animationAt(i).get());
        }
        js.pop();
    }
    if (auto count = abi->stateMachineCount())
    {
        js.pushArray("machines");
        for (size_t i = 0; i < count; ++i)
        {
            dump(js, abi->stateMachineAt(i).get());
        }
        js.pop();
    }
    js.pop();
}

static void dump(JSoner& js, rive::File* file)
{
    auto count = file->artboardCount();
    js.pushArray("artboards");
    for (size_t i = 0; i < count; ++i)
    {
        dump(js, file->artboardAt(i).get());
    }
    js.pop();
}

static rcp<rive::File> open_file(const char name[])
{
    FILE* f = fopen(name, "rb");
    if (!f)
    {
        return nullptr;
    }

    fseek(f, 0, SEEK_END);
    auto length = ftell(f);
    fseek(f, 0, SEEK_SET);

    std::vector<uint8_t> bytes(length);

    if (fread(bytes.data(), 1, length, f) != length)
    {
        printf("Failed to read file into bytes array\n");
        return nullptr;
    }

    static rive::NoOpFactory gFactory;
    return rive::File::import(bytes, &gFactory);
}

static bool is_arg(const char arg[],
                   const char target[],
                   const char alt[] = nullptr)
{
    return !strcmp(arg, target) || (arg && !strcmp(arg, alt));
}

int main(int argc, const char* argv[])
{
    const char* filename = nullptr;

    for (int i = 1; i < argc; ++i)
    {
        if (is_arg(argv[i], "--file", "-f"))
        {
            filename = argv[++i];
            continue;
        }
        printf("Unrecognized argument %s\n", argv[i]);
        return 1;
    }

    if (!filename)
    {
        printf("Need --file filename\n");
        return 1;
    }

    auto file = open_file(filename);
    if (!file)
    {
        printf("Can't open %s\n", filename);
        return 1;
    }

    JSoner js;
    js.pushStruct();
    dump(js, file.get());
    return 0;
}
