#include "ModelInfo.h"

using namespace Framework;

ModelInfo::ModelInfo()
    : ReferenceCounter(),
      modelPath(),
      texturePaths(),
      transparent(false),
      size(1.0f)
{}

ModelInfo::ModelInfo(const char* modelPath,
    Framework::RCArray<Framework::Text> texturePaths,
    bool transparent,
    float size)
    : ReferenceCounter()
{
    setModelPath(modelPath);
    for (Framework::Text* t : texturePaths)
    {
        addTexturePath(*t);
    }
    setTransparent(transparent);
    setSize(size);
}

void ModelInfo::writeTo(Framework::StreamWriter* zWriter) const
{
    char len = (char)modelPath.getLength();
    zWriter->schreibe(&len, 1);
    zWriter->schreibe(modelPath.getText(), (int)len);
    short count = (short)texturePaths.getEintragAnzahl();
    zWriter->schreibe((char*)&count, 2);
    for (Text* t : texturePaths)
    {
        len = (char)t->getLength();
        zWriter->schreibe(&len, 1);
        zWriter->schreibe(t->getText(), (int)len);
    }
    zWriter->schreibe((char*)&transparent, 1);
    zWriter->schreibe((char*)&size, 4);
}

void ModelInfo::setModelPath(Framework::Text path)
{
    modelPath = path;
}

void ModelInfo::addTexturePath(Framework::Text path)
{
    texturePaths.add(new Framework::Text(path));
}

void ModelInfo::setTransparent(bool transparent)
{
    this->transparent = transparent;
}

void ModelInfo::setSize(float size)
{
    this->size = size;
}

Framework::Text ModelInfo::getModelPath() const
{
    return modelPath;
}

Framework::RCArray<Framework::Text> ModelInfo::getTexturePaths() const
{
    return texturePaths;
}

bool ModelInfo::isTransparent() const
{
    return transparent;
}

float ModelInfo::getSize() const
{
    return size;
}

ModelInfoFactory::ModelInfoFactory()
    : ObjectTypeFactory()
{}

ModelInfo* ModelInfoFactory::fromJson(Framework::JSON::JSONObject* zJson) const
{
    ModelInfo* result = new ModelInfo();
    result->setModelPath(
        zJson->asObject()->zValue("modelPath")->asString()->getString());
    for (Framework::JSON::JSONValue* v :
        *zJson->asObject()->zValue("texturePaths")->asArray())
    {
        result->addTexturePath(v->asString()->getString());
    }
    result->setTransparent(
        zJson->asObject()->zValue("transparent")->asBool()->getBool());
    result->setSize(
        (float)zJson->asObject()->zValue("size")->asNumber()->getNumber());
    return result;
}

Framework::JSON::JSONObject* ModelInfoFactory::toJsonObject(
    ModelInfo* zObject) const
{
    Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
    Framework::JSON::JSONArray* arr = new Framework::JSON::JSONArray();
    for (Framework::Text* t : zObject->texturePaths)
    {
        arr->addValue(new Framework::JSON::JSONString(t->getText()));
    }
    result->addValue("texturePaths", arr);
    result->addValue(
        "modelPath", new Framework::JSON::JSONString(zObject->modelPath));
    result->addValue(
        "transparent", new Framework::JSON::JSONBool(zObject->transparent));
    result->addValue("size", new Framework::JSON::JSONNumber(zObject->size));
    return result;
}

JSONObjectValidationBuilder* ModelInfoFactory::addToValidator(
    JSONObjectValidationBuilder* builder) const
{
    return builder->withRequiredArray("texturePaths")
        ->addAcceptedStringInArray()
        ->finishString()
        ->finishArray()
        ->withRequiredString("modelPath")
        ->finishString()
        ->withRequiredBool("transparent")
        ->withDefault(false)
        ->finishBool()
        ->withRequiredNumber("size")
        ->whichIsGreaterThen(0)
        ->withDefault(1.0)
        ->finishNumber();
}