/***************************************************************************
*   Copyright (C) 2008 by S. MANKOWSKI / G. DE BURE support@mankowski.fr  *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
*   This program is distributed in the hope that it will be useful,       *
*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
*   GNU General Public License for more details.                          *
*                                                                         *
*   You should have received a copy of the GNU General Public License     *
*   along with this program.  If not, see <http://www.gnu.org/licenses/>  *
***************************************************************************/
/** @file
* This file defines classes SKGBudgetRuleObject.
*
* @author Stephane MANKOWSKI / Guillaume DE BURE
*/
#include "skgbudgetruleobject.h"

#include <KLocale>

#include "skgbudgetobject.h"
#include "skgdocumentbank.h"
#include "skgtraces.h"
#include "skgcategoryobject.h"
#include "skgtransactionmng.h"

SKGBudgetRuleObject::SKGBudgetRuleObject(SKGDocument* iDocument, int iID)
    : SKGObjectBase(iDocument, "v_budgetrule", iID)
{
}

SKGBudgetRuleObject::~SKGBudgetRuleObject()
{
}

SKGBudgetRuleObject::SKGBudgetRuleObject(const SKGBudgetRuleObject& iObject)
    : SKGObjectBase(iObject)
{
}

SKGBudgetRuleObject::SKGBudgetRuleObject(const SKGObjectBase& iObject)
{
    if (iObject.getRealTable() == "budgetrule") {
        copyFrom(iObject);
    } else {
        *this = SKGObjectBase(iObject.getDocument(), "v_budgetrule", iObject.getID());
    }
}

const SKGBudgetRuleObject& SKGBudgetRuleObject::operator= (const SKGObjectBase& iObject)
{
    copyFrom(iObject);
    return *this;
}

SKGError SKGBudgetRuleObject::enableYearCondition(bool iEnable)
{
    return setAttribute("t_year_condition", iEnable ? "Y" : "N");
}

int SKGBudgetRuleObject::isYearConditionEnabled() const
{
    return (getAttribute("t_year_condition") == "Y");
}

SKGError SKGBudgetRuleObject::enableMonthCondition(bool iEnable)
{
    return setAttribute("t_month_condition", iEnable ? "Y" : "N");
}

int SKGBudgetRuleObject::isMonthConditionEnabled() const
{
    return (getAttribute("t_month_condition") == "Y");
}

SKGError SKGBudgetRuleObject::enableCategoryCondition(bool iEnable)
{
    return setAttribute("t_category_condition", iEnable ? "Y" : "N");
}

int SKGBudgetRuleObject::isCategoryConditionEnabled() const
{
    return (getAttribute("t_category_condition") == "Y");
}

SKGError SKGBudgetRuleObject::setBudgetYear(int iYear)
{
    return setAttribute("i_year", SKGServices::intToString(iYear));
}

int SKGBudgetRuleObject::getBudgetYear() const
{
    return SKGServices::stringToInt(getAttribute("i_year"));
}

SKGError SKGBudgetRuleObject::setBudgetMonth(int iMonth)
{
    return setAttribute("i_month", SKGServices::intToString(iMonth));
}

int SKGBudgetRuleObject::getBudgetMonth() const
{
    return SKGServices::stringToInt(getAttribute("i_month"));
}

SKGError SKGBudgetRuleObject::setBudgetCategory(const SKGCategoryObject& iCategory)
{
    return setAttribute("rc_category_id", SKGServices::intToString(iCategory.getID()));;
}

SKGError SKGBudgetRuleObject::getBudgetCategory(SKGCategoryObject& oCategory) const
{
    return getDocument()->getObject("v_category", "id=" % getAttribute("rc_category_id"), oCategory);
}

SKGError SKGBudgetRuleObject::removeBudgetCategory()
{
    return setAttribute("rc_category_id", "0");
}

SKGError SKGBudgetRuleObject::setCondition(SKGBudgetRuleObject::Condition iCondition)
{
    return setAttribute("i_condition", SKGServices::intToString(static_cast<int>(iCondition)));
}

SKGBudgetRuleObject::Condition SKGBudgetRuleObject::getCondition() const
{
    return static_cast<SKGBudgetRuleObject::Condition>(SKGServices::stringToInt(getAttribute("i_condition")));
}

SKGError SKGBudgetRuleObject::setQuantity(double iQuantity, bool iAbsolute)
{
    SKGError err = setAttribute("f_quantity", SKGServices::doubleToString(iQuantity));
    IFOKDO(err, setAttribute("t_absolute", iAbsolute ? "Y" : "N"))
    return err;
}

double SKGBudgetRuleObject::getQuantity() const
{
    return SKGServices::stringToDouble(getAttribute("f_quantity"));
}

bool SKGBudgetRuleObject::isAbolute() const
{
    return getAttribute("t_absolute") != "N";
}

SKGError SKGBudgetRuleObject::enableCategoryChange(bool iEnable)
{
    return setAttribute("t_category_target", iEnable ? "Y" : "N");
}

int SKGBudgetRuleObject::isCategoryChangeEnabled() const
{
    return getAttribute("t_category_target") == "Y";
}

SKGError SKGBudgetRuleObject::setTransfer(SKGBudgetRuleObject::Mode iMode, const SKGCategoryObject& iCategory)
{
    SKGError err = setAttribute("t_rule", iMode == NEXT ? "N" : iMode == CURRENT ? "C" : "Y");
    IFOKDO(err, setAttribute("rc_category_id_target", SKGServices::intToString(iCategory.getID()));)
    return err;
}

SKGBudgetRuleObject::Mode SKGBudgetRuleObject::getTransferMode() const
{
    return (getAttribute("t_rule") == "N" ? NEXT : (getAttribute("t_rule") == "C" ? CURRENT : YEAR));
}

SKGError SKGBudgetRuleObject::getTransferCategory(SKGCategoryObject& oCategory) const
{
    return getDocument()->getObject("v_category", "id=" % getAttribute("rc_category_id_target"), oCategory);
}

SKGError SKGBudgetRuleObject::processAllRules(SKGDocumentBank* iDocument)
{
    SKGError err;
    SKGTRACEINFUNCRC(10, err);
    if (iDocument) {
        // Initialize
        err = iDocument->executeSqliteOrder("UPDATE budget SET f_budgeted_modified=f_budgeted  WHERE f_budgeted_modified!=f_budgeted");
        IFOKDO(err, iDocument->executeSqliteOrder("UPDATE budget SET f_transferred=0  WHERE f_transferred!=0"))

        // Get budgets ordered by date
        SKGObjectBase::SKGListSKGObjectBase budgets;
        IFOKDO(err, iDocument->getObjects("vm_budget_tmp", "length(t_RULES)>0 "
                                          "AND (t_PERIOD<=STRFTIME('%Y-%m', date('now')) OR t_PERIOD=STRFTIME('%Y', date('now'))) "
                                          "ORDER BY t_PERIOD, id", budgets));
        int nb = budgets.count();
        if (!err && nb) {
            err = iDocument->beginTransaction("#INTERNAL#" % i18nc("Progression step", "Apply rules"), nb);
            for (int i = 0; !err && i < nb; ++i) {
                SKGBudgetObject bud(budgets.at(i));
                err = bud.load();  // Reload to be sure that delta has been updated
                IFOKDO(err, bud.process())

                IFOKDO(err, iDocument->stepForward(i + 1))
            }

            IFOKDO(err, iDocument->setParameter("SKG_LAST_BUDGET_PROCESSING", QDate::currentDate().toString("yyyy-MM-dd")))

            SKGENDTRANSACTION(iDocument,  err);
        }
    }

    return err;
}

#include "skgbudgetruleobject.moc"
