#include "AdvFuncCombToElementContainer.hh"

const std::string AdvFuncCombToElementContainer::className=std::string("AdvFuncCombToElementContainer");

ElementContainer AdvFuncCombToElementContainer::create(const std::string& xkey, const std::string& ykey, const std::string& ekey, const std::string& xunit, const std::string& yunit, const std::vector<Double>& bins, const Double c) {

    std::vector<Double> x = std::vector<Double>(bins.size()-1);
    for (UInt4 i=0; i<x.size(); ++i) {
        x.at(i) = (1.0-c)*bins.at(i) + c*bins.at(i+1);
    }

    std::vector<Double> y = this->eval(x);
    std::vector<Double> e = this->evalError(x);

    ElementContainer *ec = new ElementContainer();
    ec->Add(xkey, bins, xunit);
    ec->Add(ykey, y,    yunit);
    ec->Add(ekey, e,    yunit);
    ec->SetKeys(xkey, ykey, ekey);

    return *ec;
}

ElementContainer AdvFuncCombToElementContainer::create(const std::vector<std::string>& keys, const std::vector<std::string>& units, const std::vector<Double>& bins, const Double c) {
    return this->create(keys.at(0), keys.at(1), keys.at(2), units.at(0), units.at(0), bins, c);
}

ElementContainer AdvFuncCombToElementContainer::create(const std::string& xkey, const std::string& ykey, const std::string& ekey, const std::string& xunit, const std::string& yunit, PyObject* bins, const Double c) {

    CppToPython tool;
    std::vector<Double> vectorBin = tool.ListToDoubleVector(bins);
    return this->create(xkey, ykey, ekey, xunit, yunit, vectorBin, c);
}

ElementContainer AdvFuncCombToElementContainer::create(PyObject* keys, PyObject* units, PyObject* bins, const Double c) {
    std::string memberName = std::string("create(PyObject* keys, PyObject* units, PyObject* bins, Double)");
    StringTools stool;
    CppToPython ctool;

    std::vector<std::string> vectorKeys = ctool.ListToStringVector(keys);
    if (vectorKeys.size() < 3) { // check the number of keys
        errorMessage(className, memberName, __FILE__, __LINE__, "too few key\n");
        throw std::invalid_argument(className + "::" + memberName + ':' + __FILE__ + ':' + stool.Int4ToString(__LINE__) + ": too few key\n");
    } else {
        for (UInt4 i=0; i<3; ++i) {
            if (vectorKeys.at(1).empty()) {
                errorMessage(className, memberName, __FILE__, __LINE__, "%dth key is empty\n");
                throw std::invalid_argument(className + "::" + memberName + ':' + __FILE__ + ':' + stool.Int4ToString(__LINE__) + ": " + stool.Int4ToString(i) + " key is empty.\n");
            }
        }
    }

    std::vector<std::string> vectorUnits = ctool.ListToStringVector(keys);
    if (vectorKeys.size() < 2) { // check the number of units
        errorMessage(className, memberName, __FILE__, __LINE__, "too few unit std::string\n");
        throw std::invalid_argument(className + "::" + memberName + ':' + __FILE__ + ':' + stool.Int4ToString(__LINE__) + ':' + "too few unit\n");
    }

    std::vector<Double> vectorBins = ctool.ListToDoubleVector(bins);
    return this->create(vectorKeys, vectorUnits, vectorBins, c);
}

