/***************************************************************************
 *   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 is a test script.
 *
 * @author Stephane MANKOWSKI / Guillaume DE BURE
 */
#include "skgtestmacro.h"
#include "skgbankincludes.h"

/**
 * The main function of the unit test
 * @param argc the number of arguments
 * @param argv the list of arguments
 */
int main(int argc, char** argv)
{
    Q_UNUSED(argc);
    Q_UNUSED(argv);

    // Init test
    SKGINITTEST(true);

    QDate now = QDate::currentDate();

    {
        // Test objectbase
        SKGDocumentBank document1;
        SKGTESTERROR("document1.initialize()", document1.initialize(), true);
        SKGError err;
        {
            SKGTEST("DOC:getDisplay", document1.getDisplay("v_node.unknown"), "v_node.unknown");
            SKGTEST("DOC:getDisplay", document1.getDisplay("t_comment"), "Comment");

            SKGServices::SKGAttributesList undoredoAttributes;
            SKGTESTERROR("OBJBASE:getAttributesDescription)", document1.getAttributesDescription("doctransaction", undoredoAttributes), true);
            SKGTEST("OBJBASE:undoredoAttributes.count", undoredoAttributes.count(), 7);
            SKGTEST("OBJBASE:undoredoAttributes.name", undoredoAttributes[0].name, "id");
            SKGTEST("OBJBASE:undoredoAttributes.type", static_cast<unsigned int>(undoredoAttributes[0].type), static_cast<unsigned int>(SKGServices::ID));
            SKGTESTBOOL("OBJBASE:undoredoAttributes.notnull", undoredoAttributes[0].notnull, false);
            SKGTEST("OBJBASE:undoredoAttributes.defaultvalue", undoredoAttributes[0].defaultvalue, "");
            SKGTEST("OBJBASE:undoredoAttributes.name", undoredoAttributes[2].name, "t_mode");
            SKGTEST("OBJBASE:undoredoAttributes.type", static_cast<unsigned int>(undoredoAttributes[2].type), static_cast<unsigned int>(SKGServices::TEXT));
            SKGTESTBOOL("OBJBASE:undoredoAttributes.notnull", undoredoAttributes[2].notnull, true);
            SKGTEST("OBJBASE:undoredoAttributes.defaultvalue", undoredoAttributes[2].defaultvalue, "'U'");
            /*
            | cid | name         | t_type       | notnull | dflt_value | pk |
            | 0   | id           | INTEGER    | 99      |            | 1  |
            | 1   | name         | TEXT       | 99      |            | 0  |
            | 2   | t_mode         | VARCHAR(1) | 0       | 'U'        | 0  |
            | 3   | d_date | DATE       | 99      |            | 0  |
            | 4   | t_savestep     | VARCHAR(1) | 0       | 'N'        | 0  |
            | 5   | parent       | INTEGER    | 0       |            | 0  |
            */

            QStringList undoredoAttributeNames;
            SKGTESTERROR("OBJBASE:getAttributesList)", document1.getAttributesList("doctransaction", undoredoAttributeNames), true);
            SKGTEST("OBJBASE:undoredoAttributeNames.count", undoredoAttributeNames.count(), 7);
            SKGTEST("OBJBASE:undoredoAttributeNames", undoredoAttributeNames[0], "id");
            SKGTEST("OBJBASE:undoredoAttributeNames", undoredoAttributeNames[1], "t_name");
            SKGTEST("OBJBASE:undoredoAttributeNames", undoredoAttributeNames[2], "t_mode");
            SKGTEST("OBJBASE:undoredoAttributeNames", undoredoAttributeNames[3], "d_date");
            SKGTEST("OBJBASE:undoredoAttributeNames", undoredoAttributeNames[4], "t_savestep");
            SKGTEST("OBJBASE:undoredoAttributeNames", undoredoAttributeNames[5], "t_refreshviews");
            SKGTEST("OBJBASE:undoredoAttributeNames", undoredoAttributeNames[6], "i_parent");

            SKGBEGINTRANSACTION(document1, "OBJBASE 1", err);
            SKGObjectBase obj1(&document1, "bank");
            SKGTESTERROR("OBJBASE:setAttribute", obj1.setAttribute("t_name", "CL"), true);
            SKGTESTERROR("OBJBASE:save", obj1.save(), true);

            SKGObjectBase obj2(&document1, "bank", obj1.getID());
            SKGTESTERROR("OBJBASE:load", obj2.load(), true);
            SKGTEST("OBJBASE:getAttribute", obj2.getAttribute("t_name"), "CL");
            SKGTESTERROR("OBJBASE:setAttribute", obj2.setAttribute("t_name", "CC"), true);
            SKGTESTERROR("OBJBASE:save", obj2.save(), true);

            SKGObjectBase obj3(&document1, "v_bank", obj2.getID());
            SKGTESTERROR("OBJBASE:load", obj3.load(), true);
            SKGTEST("OBJBASE:getAttribute", obj3.getAttribute("t_name"), "CC");
            SKGTEST("OBJBASE:getTable", obj3.getTable(), "v_bank");
            SKGTESTERROR("OBJBASE:save", obj3.save(), true);

            SKGObjectBase obj4(&document1);
            SKGTESTBOOL("OBJBASE:Operator =", (obj2 == obj1), true);
            SKGTESTBOOL("OBJBASE:Operator =", (obj3 == obj1), true);
            SKGTESTBOOL("OBJBASE:Operator =", (obj4 == obj1), false);

            SKGTESTBOOL("OBJBASE:Operator !=", (obj2 != obj1), false);
            SKGTESTBOOL("OBJBASE:Operator !=", (obj3 != obj1), false);
            SKGTESTBOOL("OBJBASE:Operator !=", (obj4 != obj1), true);

            SKGQStringQStringMap att = obj3.getAttributes();
            int nb = obj3.getNbAttributes();
            SKGTEST("OBJBASE:getNbAttributes", obj3.getNbAttributes(), att.count());
            for (int i = 0; i < nb; ++i) {
                SKGTRACE << i << ":" << obj3.getAttribute(SKGServices::intToString(i)) << endl;
            }
            SKGTEST("OBJBASE:getAttribute", obj3.getAttribute("2"), "CC");
            SKGTESTBOOL("OBJBASE:exist", obj3.exist(), true);
            SKGTESTERROR("OBJBASE:dump", obj3.dump(), true);

            SKGTEST("OBJBASE:getID", obj3.getID(), 1);
            SKGTESTERROR("OBJBASE:resetID", obj3.resetID(), true);
            SKGTEST("OBJBASE:getID", obj3.getID(), 0);

            SKGNamedObject tmp1(obj3);
            SKGNamedObject tmp2 = tmp1;
            SKGTEST("OBJBASE:getAttribute", tmp2.getAttribute("t_name"), "CC");

            // Test error
            SKGObjectBase notFound;
            SKGTESTERROR("OBJBASE:getObject", document1.getObject("v_bank", "t_name='NOTFOUND'", notFound), false);
            SKGTESTERROR("OBJBASE:getObject", document1.getObject("parameters", "'", notFound), false);
            SKGTESTERROR("OBJBASE:getObject", document1.getObject("v_bank", 9999, notFound), false);
        }
    }
    // ============================================================================
    // ============================================================================
    {
        // Test bank document
        SKGDocumentBank document1;
        SKGTESTERROR("document1.initialize()", document1.initialize(), true);
        SKGError err;
        SKGTEST("BANK:getNbTransaction", document1.getNbTransaction(), 0);
        {
            // Scope of the transaction
            SKGBEGINTRANSACTION(document1, "BANK_T1", err);

            // The code here
            IFOK(err) {
                SKGTEST("BANK:getDepthTransaction", document1.getDepthTransaction(), 1);

                // Example; operation succeeded
                SKGTESTERROR("BANK:setParameter", document1.setParameter("ATT1", "VAL1"), true);
                SKGTESTERROR("BANK:setParameter", document1.setParameter("ATT2", "VAL2"), true);
                SKGTESTERROR("BANK:setParameter", document1.setParameter("ATT3", "VAL2"), true);

                QStringList oResult;
                SKGTESTERROR("BANK:getDistinctValues", document1.getDistinctValues("parameters", "t_value", "t_value like 'VAL%'", oResult), true);
                SKGTEST("BANK:oResult.size", oResult.size(), 2);

                // Test account
                SKGTESTERROR("BANK:addOrModifyAccount", document1.addOrModifyAccount("Courant", "123", "LCL"), true);
                SKGTESTERROR("BANK:addOrModifyAccount", document1.addOrModifyAccount("Livret A", "456", "CREDIT COOP"), true);
                SKGTESTERROR("BANK:addOrModifyAccount", document1.addOrModifyAccount("Codevi", "789", "NEF"), true);
                SKGTESTERROR("BANK:addOrModifyAccount", document1.addOrModifyAccount("PEA", "ABC", "CA"), true);
                SKGTESTERROR("BANK:getDistinctValues", document1.getDistinctValues("account", "t_name", oResult), true);
                SKGTEST("BANK:oResult.size", oResult.size(), 4);

                // Test units
                SKGTESTERROR("BANK:addOrModifyUnitValue", document1.addOrModifyUnitValue("E", now, 1), true);
                SKGTESTERROR("BANK:addOrModifyUnitValue", document1.addOrModifyUnitValue("$", now, 1.6), true);  // Oups, it's an error
                SKGTESTERROR("BANK:addOrModifyUnitValue", document1.addOrModifyUnitValue("$", now, 0.625), true);  // it's better now
                SKGTESTERROR("BANK:getDistinctValues", document1.getDistinctValues("unitvalue", "rd_unit_id", oResult), true);
                SKGTEST("BANK:oResult.size", oResult.size(), 2);
            }
        }  // A commit is done here because the scope is close

        QStringList oResult;
        SKGTESTERROR("BANK:getDistinctValues", document1.getDistinctValues("unit", "t_name", oResult), true);
        SKGTEST("BANK:oResult.size", oResult.size(), 2);
        SKGTESTERROR("BANK:undoRedoTransaction(BANK_T1, SKGDocument::UNDO)", document1.undoRedoTransaction(), true);
        SKGTESTERROR("BANK:getDistinctValues", document1.getDistinctValues("unit", "t_name", oResult), true);
        SKGTEST("BANK:oResult.size", oResult.size(), 0);
        SKGTESTERROR("BANK:undoRedoTransaction(BANK_T1, SKGDocument::REDO)", document1.undoRedoTransaction(SKGDocument::REDO), true);
        SKGTESTERROR("BANK:getDistinctValues", document1.getDistinctValues("unit", "t_name", oResult), true);
        SKGTEST("BANK:oResult.size", oResult.size(), 2);

        SKGTESTERROR("BANK:err", err, true);
    }

    // End test
    SKGENDTEST();
}
