/***************************************************************************
 *   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"

/**
 * 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);

    {
        // Test node
        SKGDocument document1;
        SKGTESTERROR("document1.initialize()", document1.initialize(), true);
        SKGError err;
        SKGNodeObject parent2;
        {
            // Scope of the transaction
            SKGBEGINTRANSACTION(document1, "NODE_T1", err);

            // Create node 0
            SKGNodeObject nod0(&document1);
            SKGTESTERROR("NOD:setName+invalid name", nod0.setName('a' % OBJECTSEPARATOR % 'b'), false);
            SKGTESTERROR("NOD:save", nod0.save(), false);

            // Create node 1
            SKGNodeObject nod1(&document1);
            SKGTESTERROR("NOD:setName", nod1.setName("root1"), true);
            SKGTESTERROR("NOD:setData", nod1.setData("data1"), true);
            SKGTESTERROR("NOD:setOrder", nod1.setOrder(12), true);
            SKGTESTERROR("NOD:setAutoStart", nod1.setAutoStart(true), true);
            SKGTESTBOOL("NOD:exist", nod1.exist(), false);
            SKGTESTERROR("NOD:save", nod1.save(), true);
            SKGTESTBOOL("NOD:exist", nod1.exist(), true);
            SKGTEST("NOD:getFullName", nod1.getFullName(), "root1");
            SKGTEST("NOD:getData", nod1.getData(), "data1");
            SKGTEST("NOD:getOrder", nod1.getOrder(), 12);
            SKGTESTBOOL("NOD:isFolder", nod1.isFolder(), false);
            SKGTESTBOOL("NOD:isAutoStart", nod1.isAutoStart(), true);
            nod1.getIcon();

            // Update with bad name
            SKGTESTERROR("NOD:setName", nod1.setName("root1" % OBJECTSEPARATOR % 'A'), false);
            SKGTESTERROR("NOD:load", nod1.load(), true);
            SKGTEST("NOD:getFullName", nod1.getFullName(), "root1");

            // Create node 1.1
            SKGNodeObject nod1_1;
            SKGTESTERROR("NOD:addNode", nod1.addNode(nod1_1), true);
            SKGTESTERROR("NOD:setName", nod1_1.setName("nod1"), true);
            SKGTESTERROR("NOD:setOrder", nod1_1.setOrder(1), true);
            SKGTESTERROR("NOD:save", nod1_1.save(), true);
            SKGTEST("NOD:getFullName", nod1_1.getFullName(), "root1" % OBJECTSEPARATOR % "nod1");

            // Update nod1_1
            SKGTESTERROR("NOD:setName", nod1_1.setName("NODE1"), true);
            SKGTESTERROR("NOD:save", nod1_1.save(), true);
            SKGTEST("NOD:getFullName", nod1_1.getFullName(), "root1" % OBJECTSEPARATOR % "NODE1");

            // Update nod1
            SKGTESTERROR("NOD:setName", nod1.setName("ROOT1"), true);
            SKGTESTERROR("NOD:save", nod1.save(), true);
            SKGTEST("NOD:getFullName", nod1.getFullName(), "ROOT1");

            SKGTESTERROR("NOD:load", nod1_1.load(), true);
            SKGTEST("NOD:getFullName", nod1_1.getFullName(), "ROOT1" % OBJECTSEPARATOR % "NODE1");

            // Create node 1.2
            SKGNodeObject nod1_2;
            SKGTESTERROR("NOD:addNode", nod1.addNode(nod1_2), true);
            SKGTESTERROR("NOD:setName", nod1_2.setName("NODE2"), true);
            SKGTESTERROR("NOD:setOrder", nod1_2.setOrder(2), true);
            SKGTESTERROR("NOD:save", nod1_2.save(), true);
            SKGTEST("NOD:getFullName", nod1_2.getFullName(), "ROOT1" % OBJECTSEPARATOR % "NODE2");
            SKGTESTBOOL("NOD:<", (nod1_1 < nod1_2), true);
            SKGTESTBOOL("NOD:>", (nod1_1 > nod1_2), false);
            SKGTESTBOOL("NOD:<", (nod1_1 < nod1_1), false);
            SKGTESTBOOL("NOD:>", (nod1_1 > nod1_1), false);

            // Create node end
            SKGNodeObject end1;
            SKGTESTERROR("NOD:addNode", nod1_1.addNode(end1), true);
            SKGTESTERROR("NOD:setName", end1.setName("END"), true);
            SKGTESTERROR("NOD:save", end1.save(), true);
            SKGTEST("NOD:getFullName", end1.getFullName(), "ROOT1" % OBJECTSEPARATOR % "NODE1" % OBJECTSEPARATOR % "END");

            // Create node end
            SKGNodeObject end2;
            SKGTESTERROR("NOD:addNode", nod1_2.addNode(end2), true);
            SKGTESTERROR("NOD:setName", end2.setName("END"), true);
            SKGTESTERROR("NOD:save", end2.save(), true);
            SKGTEST("NOD:getFullName", end2.getFullName(), "ROOT1" % OBJECTSEPARATOR % "NODE2" % OBJECTSEPARATOR % "END");

            SKGNodeObject end2_1;
            SKGTESTERROR("NOD:addNode", end2.addNode(end2_1), true);
            SKGTESTERROR("NOD:setName", end2_1.setName("REALEND"), true);
            SKGTESTERROR("NOD:save", end2_1.save(), true);
            SKGTEST("NOD:getFullName", end2_1.getFullName(), "ROOT1" % OBJECTSEPARATOR % "NODE2" % OBJECTSEPARATOR % "END" % OBJECTSEPARATOR % "REALEND");

            // Get parent
            SKGNodeObject parent1;
            SKGTESTERROR("NOD:addNode", end2.getParentNode(parent1), true);
            SKGTEST("NOD:getFullName", parent1.getFullName(), "ROOT1" % OBJECTSEPARATOR % "NODE2");

            // Get parent
            SKGTESTERROR("NOD:addNode", parent1.getParentNode(parent2), true);
            SKGTEST("NOD:getFullName", parent2.getFullName(), "ROOT1");

            // Get children
            SKGObjectBase::SKGListSKGObjectBase NodeList;
            SKGTESTERROR("NOD:getNodes", parent2.getNodes(NodeList), true);
            SKGTEST("NOD:nb nodegories", NodeList.size(), 2);

            // Simple delete
            SKGTESTERROR("NOD:delete", end1.remove(), true);
            QStringList oResult;
            SKGTESTERROR("NOD:getDistinctValues", document1.getDistinctValues("node", "id", oResult), true);
            SKGTEST("NOD:oResult.size", oResult.size(), 5);

            SKGNodeObject nodeROOT1BC;
            SKGTESTERROR("NOD:addNode", SKGNodeObject::createPathNode(&document1, "ROOT1" % OBJECTSEPARATOR % 'B' % OBJECTSEPARATOR % 'C', nodeROOT1BC), true);

            SKGNodeObject nodeROOT1DE;
            SKGTESTERROR("NOD:addNode", SKGNodeObject::createPathNode(&document1, "ROOT1" % OBJECTSEPARATOR % 'D' % OBJECTSEPARATOR % 'E', nodeROOT1DE), true);
        }
        {
            // Scope of the transaction
            SKGBEGINTRANSACTION(document1, "NODE_T2", err);

            // Cascading delete
            SKGTESTERROR("NOD:delete", parent2.remove(), true);
            QStringList oResult;
            SKGTESTERROR("NOD:getDistinctValues", document1.getDistinctValues("node", "id", oResult), true);
            SKGTEST("NOD:oResult.size", oResult.size(), 0);
        }

        // Undo
        SKGTESTERROR("NOD:undoRedoTransaction", document1.undoRedoTransaction(), true);
        QStringList oResult;
        SKGTESTERROR("NOD:getDistinctValues", document1.getDistinctValues("node", "id", oResult), true);
        SKGTEST("NOD:oResult.size", oResult.size(), 9);

        SKGTESTERROR("NOD:undoRedoTransaction", document1.undoRedoTransaction(), true);
        SKGTESTERROR("NOD:getDistinctValues", document1.getDistinctValues("node", "id", oResult), true);
        SKGTEST("NOD:oResult.size", oResult.size(), 0);

        // Redo
        SKGTESTERROR("NOD:undoRedoTransaction(SKGDocument::REDO)", document1.undoRedoTransaction(SKGDocument::REDO), true);
        SKGTESTERROR("NOD:getDistinctValues", document1.getDistinctValues("node", "id", oResult), true);
        SKGTEST("NOD:oResult.size", oResult.size(), 9);

        SKGTESTERROR("NOD:undoRedoTransaction(SKGDocument::REDO)", document1.undoRedoTransaction(SKGDocument::REDO), true);
        SKGTESTERROR("NOD:getDistinctValues", document1.getDistinctValues("node", "id", oResult), true);
        SKGTEST("NOD:oResult.size", oResult.size(), 0);
    }

    {
        SKGDocument document1;
        SKGTESTERROR("document1.initialize()", document1.initialize(), true);
        SKGError err;
        {
            // Scope of the transaction
            SKGBEGINTRANSACTION(document1, "NODE_T1", err);

            SKGNodeObject node;
            SKGTESTERROR("NOD:createPathNode", SKGNodeObject::createPathNode(&document1, 'A' % OBJECTSEPARATOR % "B1" % OBJECTSEPARATOR % 'C', node), true);
            SKGTESTERROR("NOD:createPathNode", SKGNodeObject::createPathNode(&document1, 'A' % OBJECTSEPARATOR % "B1" % OBJECTSEPARATOR % 'D', node), true);
            SKGTESTERROR("NOD:createPathNode", SKGNodeObject::createPathNode(&document1, 'A' % OBJECTSEPARATOR % "B2" % OBJECTSEPARATOR % 'E', node), true);
            QStringList oResult;
            SKGTESTERROR("NOD:getDistinctValues", document1.getDistinctValues("node", "id", oResult), true);
            SKGTEST("NOD:oResult.size", oResult.size(), 6);
        }
    }

    {
        SKGDocument document1;
        SKGTESTERROR("document1.initialize()", document1.initialize(), true);
        SKGError err;
        {
            // Scope of the transaction
            SKGBEGINTRANSACTION(document1, "NODE_T1", err);

            SKGNodeObject node;
            SKGTESTERROR("NOD:createPathNode", SKGNodeObject::createPathNode(&document1, 'A' % OBJECTSEPARATOR % "B1" % OBJECTSEPARATOR % 'C', node), true);
            SKGTESTERROR("NOD:createPathNode", SKGNodeObject::createPathNode(&document1, 'A' % OBJECTSEPARATOR % "B2" % OBJECTSEPARATOR % 'C', node), true);
            QStringList oResult;
            SKGTESTERROR("NOD:getDistinctValues", document1.getDistinctValues("node", "id", oResult), true);
            SKGTEST("NOD:oResult.size", oResult.size(), 5);
        }
    }

    {
        SKGDocument document1;
        SKGTESTERROR("document1.initialize()", document1.initialize(), true);
        SKGError err;
        {
            // Scope of the transaction
            SKGBEGINTRANSACTION(document1, "NODE_T1", err);

            SKGNodeObject node;
            SKGTESTERROR("NOD:createPathNode", SKGNodeObject::createPathNode(&document1, 'A' % OBJECTSEPARATOR % 'A', node), true);
            QStringList oResult;
            SKGTESTERROR("NOD:getDistinctValues", document1.getDistinctValues("node", "id", oResult), true);
            SKGTEST("NOD:oResult.size", oResult.size(), 2);
        }
    }

    {
        SKGDocument document1;
        SKGTESTERROR("document1.initialize()", document1.initialize(), true);
        SKGError err;
        {
            // Scope of the transaction
            SKGBEGINTRANSACTION(document1, "NODE_T1", err);

            SKGNodeObject nodeB;
            SKGTESTERROR("NOD:createPathNode", SKGNodeObject::createPathNode(&document1, 'A' % OBJECTSEPARATOR % 'B', nodeB), true);
            SKGNodeObject nodeC;
            SKGTESTERROR("NOD:createPathNode", SKGNodeObject::createPathNode(&document1, "C", nodeC), true);
            SKGNodeObject nodeA;
            SKGTESTERROR("NOD:getParentNode", nodeB.getParentNode(nodeA), true);

            SKGNamedObject nameB = static_cast<SKGNamedObject>(nodeB);  // For coverage
            SKGNodeObject nodeC2(static_cast<SKGObjectBase>(nodeC));  // For coverage

            SKGTESTERROR("NOD:setParentNode", nodeA.setParentNode(nodeB), false);
            SKGTESTERROR("NOD:setParentNode", nodeA.setParentNode(nodeA), false);
            SKGTESTERROR("NOD:setParentNode", nodeB.setParentNode(nodeB), false);
            SKGTESTERROR("NOD:setParentNode", nodeC.setParentNode(nodeB), true);
            SKGTESTERROR("NOD:removeParentNode", nodeB.removeParentNode(), true);
        }
    }

    {
        SKGDocument document1;
        SKGTESTERROR("document1.initialize()", document1.initialize(), true);
        SKGError err;
        {
            // Scope of the transaction
            SKGBEGINTRANSACTION(document1, "NODE_T1", err);

            SKGNodeObject nodeB1;
            SKGTESTERROR("NOD:createPathNode", SKGNodeObject::createPathNode(&document1, 'A' % OBJECTSEPARATOR % 'B', nodeB1, true), true);
            SKGNodeObject nodeB2;
            SKGTESTERROR("NOD:createPathNode", SKGNodeObject::createPathNode(&document1, 'A' % OBJECTSEPARATOR % 'B', nodeB2, true), true);
            document1.dump(DUMPALL);

            QStringList oResult;
            SKGTESTERROR("NOD:getDistinctValues", document1.getDistinctValues("node", "id", oResult), true);
            SKGTEST("NOD:oResult.size", oResult.size(), 3);
        }
    }

    {
        SKGDocument document1;
        SKGTESTERROR("document1.initialize()", document1.initialize(), true);
        SKGError err;
        {
            // Scope of the transaction
            SKGBEGINTRANSACTION(document1, "NODE_T1", err);

            SKGNodeObject nodeB1;
            SKGTESTERROR("NOD:createPathNode", SKGNodeObject::createPathNode(&document1, "B", nodeB1, true), true);
            SKGNodeObject nodeB2;
            SKGTESTERROR("NOD:createPathNode", SKGNodeObject::createPathNode(&document1, "B", nodeB2, true), true);

            QStringList oResult;
            SKGTESTERROR("NOD:getDistinctValues", document1.getDistinctValues("node", "id", oResult), true);
            SKGTEST("NOD:oResult.size", oResult.size(), 2);
        }
    }

    // Test properties
    {
        SKGDocument document1;
        SKGTESTERROR("document1.initialize()", document1.initialize(), true);
        SKGError err;
        {
            // Scope of the transaction
            SKGBEGINTRANSACTION(document1, "NODE_T1", err);

            SKGNodeObject node1;
            SKGTESTERROR("NOD:createPathNode", SKGNodeObject::createPathNode(&document1, "1", node1, true), true);
            SKGNodeObject node2;
            SKGTESTERROR("NOD:createPathNode", SKGNodeObject::createPathNode(&document1, "2", node2, true), true);

            SKGTESTERROR("NOD:setProperty", node1.setProperty("prop", "val1"), true);
            SKGTESTERROR("NOD:setProperty", node2.setProperty("prop", "val2"), true);

            SKGTEST("NOD:getProperty", node1.getProperty("prop"), "val1");
            SKGTEST("NOD:getProperty", node2.getProperty("prop"), "val2");

            SKGTESTERROR("NOD:setProperty", node1.setProperty("prop", "val3"), true);

            SKGTEST("NOD:getProperty", node1.getProperty("prop"), "val3");
            SKGTEST("NOD:getProperty", node2.getProperty("prop"), "val2");
        }
    }

    // Test setAttribute
    {
        SKGDocument document1;
        SKGTESTERROR("document1.initialize()", document1.initialize(), true);
        SKGError err;
        {
            // Scope of the transaction
            SKGBEGINTRANSACTION(document1, "NODE_T1", err);

            SKGNodeObject node1;
            SKGTESTERROR("NOD:save", node1.save(), false);
            SKGTESTERROR("NOD:remove", node1.remove(), false);

            SKGNodeObject node2;
            SKGTESTERROR("NOD:addNode", node1.addNode(node2), false);
            SKGTESTERROR("NOD:setParentNode", node1.setParentNode(node2), false);

            SKGTESTERROR("NOD:createPathNode", SKGNodeObject::createPathNode(&document1, "ABC DEF ", node1, true), true);

            SKGTESTERROR("NOD:setAttribute", node1.setAttribute("t_name", "=lower"), true);
            SKGTEST("NOD:getAttribute", node1.getAttribute("t_name"), "abc def ");

            SKGTESTERROR("NOD:setAttribute", node1.setAttribute("t_name", "=upper"), true);
            SKGTEST("NOD:getAttribute", node1.getAttribute("t_name"), "ABC DEF ");

            SKGTESTERROR("NOD:setAttribute", node1.setAttribute("t_name", "=capwords"), true);
            SKGTEST("NOD:getAttribute", node1.getAttribute("t_name"), "Abc Def ");

            SKGTESTERROR("NOD:setAttribute", node1.setAttribute("t_name", "=capitalize"), true);
            SKGTEST("NOD:getAttribute", node1.getAttribute("t_name"), "Abc def ");

            SKGTESTERROR("NOD:setAttribute", node1.setAttribute("t_name", "=trim"), true);
            SKGTEST("NOD:getAttribute", node1.getAttribute("t_name"), "Abc def");
        }
    }
    // End test
    SKGENDTEST();
}
