#include "RecipieLoader.h"

#include <Datei.h>
#include <iostream>
#include <Logging.h>
#include <stdexcept>

#include "Game.h"
#include "ItemType.h"
#include "JsonUtils.h"

using namespace Framework::JSON;
using namespace Framework::Validator;

RecipieLoader::RecipieLoader()
    : Framework::ReferenceCounter(),
      validator(0)
{}

RecipieLoader::~RecipieLoader()
{
    if (validator) validator->release();
}

void RecipieLoader::loadRecipies(const char* path)
{
    DataValidator* validator
        = Framework::Validator::DataValidator::buildForArray()
              ->addAcceptedTypeInArray(
                  Game::INSTANCE->zTypeRegistry()->getValidator<Recipie>())
              ->removeInvalidEntries()
              ->finishArray();
    loadAllJsonsFromDirectory(
        path, [this, &validator](JSONValue* zJson, Framework::Text path) {
            Framework::Logging::info()
                << "loading recipies from '" << path << "'";
            Framework::RCArray<ValidationResult> invalidParts;
            JSONValue* valid = validator->getValidParts(zJson, &invalidParts);
            for (ValidationResult* invalidPart : invalidParts)
            {
                Framework::Logging::error() << invalidPart->getInvalidInfo();
            }
            int count = 0;
            if (valid)
            {
                for (JSONValue* value : *valid->asArray())
                {
                    Recipie* recipie
                        = Game::INSTANCE->zTypeRegistry()->fromJson<Recipie>(
                            value);
                    if (recipie)
                    {
                        Framework::Text group = recipie->getGroupName();
                        RecipieList* list = zRecipieList(group);
                        if (!list)
                        {
                            registerRecipieList(group);
                            list = zRecipieList(group);
                        }
                        list->addRecipie(recipie);
                        count++;
                    }
                }
            }
            Framework::Logging::info() << count << " recipies were loaded.";
        });
    Framework::JSON::JSONObject* schema = validator->getJsonSchema();
    Framework::Datei syntaxFile;
    syntaxFile.setDatei("data/syntax/schema/recipies.json");
    syntaxFile.erstellen();
    syntaxFile.open(Framework::Datei::Style::schreiben);
    syntaxFile.schreibe(schema->toString(), schema->toString().getLength());
    syntaxFile.close();
    schema->release();
    validator->release();
}

RecipieList* RecipieLoader::zRecipieList(const char* name) const
{
    for (RecipieList* l : lists)
    {
        if (l->getName().istGleich(name)) return l;
    }
    return 0;
}

void RecipieLoader::registerRecipieList(const char* name)
{
    if (zRecipieList(name))
        throw new std::invalid_argument("the recipie list already exists");
    lists.add(new RecipieList(name));
}

Framework::Text RecipieLoader::getCrafingUIML(int itemTypeId)
{
    Framework::Text result = "<dialog id=\"crafting_";
    result.append() << itemTypeId << "\"><craftingRecipies>";
    for (RecipieList* list : lists)
    {
        Framework::RCArray<Recipie> recipies;
        list->findRecipies(itemTypeId, recipies);
        if (recipies.getEintragAnzahl() > 0)
        {
            result.append()
                << "<craftingRecipieGroup name=\"" << list->getName();
            if (list->getName().istGleich("inventory"))
            {
                result.append()
                    << "\" itemIcon=\""
                    << Game::INSTANCE->getItemTypeId("Crafting Table");
            }
            result += "\">";
            for (Recipie* recipie : recipies)
            {
                result += recipie->getRecipieUIML();
            }
            result += "</craftingRecipieGroup>";
        }
    }
    result += "</craftingRecipies></dialog>";
    return result;
}