/*
 *
 *  Copyright 2010-Present Peregrine Labs. All rights reserved.
 *  (c) 2010-Present Peregrine Labs a division of Peregrine Visual Storytelling Ltd.
 *  All rights reserved.
 *
 *  The coded instructions, statements, computer programs, and/or related
 *  material (collectively the "Data") in these files contain unpublished
 *  information proprietary to Peregrine Visual Storytelling Ltd. ("Peregrine")
 *  and/or its licensors, which is protected by U.S. and Canadian federal
 *  copyright law and by international treaties.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. PEREGRINE
 *  DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTIES
 *  INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF NON-INFRINGEMENT,
 *  MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, OR ARISING FROM A COURSE
 *  OF DEALING, USAGE, OR TRADE PRACTICE. IN NO EVENT WILL PEREGRINE AND/OR ITS
 *  LICENSORS BE LIABLE FOR ANY LOST REVENUES, DATA, OR PROFITS, OR SPECIAL,
 *  DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES, EVEN IF PEREGRINE AND/OR ITS
 *  LICENSORS HAS BEEN ADVISED OF THE POSSIBILITY OR PROBABILITY OF SUCH DAMAGES.
 *
 *
 */

#include <cstdio>
#include <cstdlib>
#include <memory>

#include "Yeti/Yeti.h"

std::string dataTypeDescription(Yeti::DataType type) {
    switch (type) {
        case Yeti::DataType::Int:
            return "int";
        case Yeti::DataType::Float:
            return "float";
        case Yeti::DataType::Vector:
            return "vector";
        case Yeti::DataType::Matrix:
            return "matrix";
        case Yeti::DataType::Color:
            return "color";
    }
}

std::string attributeFlagDescription(int flags) {
    std::string result = "";
    if (flags & Yeti::AttributeFlags::VertexSetFlag)
    {
        result += "v";
    }
    if (flags & Yeti::AttributeFlags::FaceSetFlag)
    {
        result += "f";
    }
    if (flags & Yeti::AttributeFlags::ReformattedFlag)
    {
        result += "r";
    }
    if (flags & Yeti::AttributeFlags::HiddenFlag)
    {
        result += "h";
    }
    return result;
}

int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("Usage: inspectcache <fur-file> [time]\n");
        exit(1);
    }

    float frameTime = 0;
    if (argc >= 3) {
        frameTime = strtof(argv[2], nullptr);
    }

    auto furFile = std::string(argv[1]);
    auto graph = Yeti::Graph::loadFromCacheFile(furFile);

    if (!graph) {
        printf("Failed to load cache file!");
        exit(1);
    }

    Yeti::GraphExecutionOptions options;
    auto result = Yeti::executeGraph(graph, {frameTime}, options);

    for (int i = 0; i < result->geo()->numObjects(); i++) {
        auto object = result->geo()->get(i);
        auto bbox = object->boundingBox(true);

        printf("Object '%s':\n", object->name().c_str());
        printf("  bounding box: <%.1f %.1f %.1f> <%.1f %.1f %.1f>\n", bbox.min.x, bbox.min.y, bbox.min.z, bbox.max.x,
               bbox.max.y, bbox.max.z);
        printf("  %d attributes, %10d bytes\n", (int) object->attributes()->numAttributes(),
               (int) object->attributes()->memUsage());

        auto attributeNames = object->attributes()->attributeNames();
        for (auto &name : attributeNames) {
            auto attribute = object->attributes()->get(name);
            printf("    | %30s | %6s | %6d elements | %8d bytes | %s \n", name.c_str(),
                   dataTypeDescription(attribute->dataType()).c_str(),
                   attribute->numElements(),
                   (int) attribute->memUsage(),
                   attributeFlagDescription(attribute->flags()).c_str());
        }
        printf("\n");
    }
}