/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

/*
 * Author: pgess <v.melnychenko@xreate.org>
 * Created on June 25, 2018, 12:14 PM
 *
 * \file    latex.cpp
 * \brief   latex
 */

#include "query/latex.h"
#include "aux/transcend-decorators.h"

using namespace std;
using namespace xreate::latereasoning;

namespace xreate{
namespace latex{

void
LatexQuery::init(TranscendLayer* transcend) {
    __transcend = transcend;

    //schema: latex_fn_demand(Fn, Subject)
    StaticModel data = __transcend->query("latex_fn_demand_ordered");
    for(const auto& entry : data) {
        string fnName, subject; size_t id;
        tie(fnName, subject, id) = __transcend->parse<string, string, int>(entry.second);
        __demand[fnName].resize(std::max(__demand[fnName].size(), id+1));
        __demand[fnName][id] = subject;
    }

    //schema: latex_registered_subjects(Subject, Decision)
    data = __transcend->query("latex_registered_subjects");
    for(const auto& entry : data) {
        string subject;
        Gringo::Symbol decision;

        tie(subject, decision) = __transcend->parse<string, Gringo::Symbol>(entry.second);
        __domains[subject].push_back(decision);
    }
    
    //schema: latex_decision(Scope, Subject, Decision)
    data = __transcend->query("latex_decision");
    for(const auto& entry : data) {
        ScopePacked scope;
        string subject;
        Gringo::Symbol decision;

        tie(scope, subject, decision) = __transcend->parse<ScopePacked, string, Gringo::Symbol>(entry.second);
        __decisions[make_pair(scope, subject)] = entry.second;
    }
    
    //schema: latex_parameters_offset(int)
    //Override parameter from transcend
    data = __transcend->query("latex_parameters_offset");
    if(data.size()) {
        LatexParametersOffset = std::get<0>(__transcend->parse<unsigned int>(data.begin()->second));
    }
    
    auto transcendLate = 
        Decorators<LateReasoningTranscendDecoratorTag>::getInterface(__transcend);
    
    //Later decisions. schema: Scope, Subject, Decision
    LateAnnotationsGroup group = transcendLate->queryLate("latex_decision");
    for (auto entry: group.annotations) {
        auto key = __transcend->parse<ScopePacked, string>(entry.first);
        __decisionsLate.emplace(make_pair(get<0>(key), get<1>(key)), entry.second);
    }
}

Demand
LatexQuery::getFnDemand(const std::string& fnName) {
    if (!__demand.count(fnName)) return Demand();
    return __demand.at(fnName);
}

latereasoning::LateAnnotation
LatexQuery::getDecision(const std::string& subject, const CodeScope* scopeCaller) {
    ScopePacked scopeP = __transcend->pack(scopeCaller);

    if(__decisions.count(make_pair(scopeP, subject))){
        //found static decision
        return LateAnnotation(__decisions.at(make_pair(scopeP, subject)));
    }

    return __decisionsLate.at(make_pair(scopeP, subject));
}

std::list<Gringo::Symbol>
LatexQuery::getSubjectDomain(const std::string& subject) {
    assert(__domains.count(subject));
    return __domains.at(subject);
}

}
}
