#!/usr/bin/env qore
# -*- mode: qore; indent-tabs-mode: nil -*-

%new-style
%enable-all-warnings
%require-types
%strict-args

%requires ../../../../qlib/QUnit.qm

%exec-class ContextTest

class ContextTest inherits QUnit::Test {
    constructor() : QUnit::Test("Context test", "1.0") {
        addTestCase("Test", \testContext());
        set_return_value(main());
    }

    testContext() {
        hash q = ( "name" : ("david", "renata", "laura", "camilla", "isabella"),
                   "age"  : (37, 30, 7, 4, 1 ) );

        # initial matrix
        hash t = ( "name" : ("david", "renata", "laura", "camilla", "isabella"),
                   "key1" : (1, 2, 3, 4, 5),
                   "key2" : (4, 5, 6, 7, 8),
                   "key3" : (7, 8, 9, 0, 1),
                   "key4" : (2, 3, 4, 5, 6),
                   "key5" : (3, 4, 5, 6, 7) );

        # resulting transposed matrix
        hash i = ( "david"    : (1, 4, 7, 2, 3),
                   "renata"   : (2, 5, 8, 3, 4),
                   "laura"    : (3, 6, 9, 4, 5),
                   "camilla"  : (4, 7, 0, 5, 6),
                   "isabella" : (5, 8, 1, 6, 7) );

        hash h;
        context q (q) sortBy (%name)
            context t (t) where (%q:name == %name) sortBy (%key2)
                h.%q:name = (%key1, %t:key2, %key3, %key4, %key5);

        assertEq(h, i, "context");

        int age = find %age in q where (%name == "david");
        assertEq(age, 37, "find");

        list ages = find %age in q where (%name == "david" || %name == "isabella");
        assertEq(ages, (37, 1), "list find");
        context (q) {
            assertEq(%%, ("name" : "david", "age" : 37), "context row");
            assertEq(cx_first(), True, "cx_first()");
            assertEq(cx_last(), False, "cx_last()");
            assertEq(cx_pos(), 0, "cx_pos()");
            assertEq(cx_total(), 5, "cx_total()");
            assertEq(cx_value("name"), "david", "cx_value()");
            break;
        }

        HashListIterator qi(q);
        while (qi.next()) {
            assertEq(qi.getRow(), ("name" : "david", "age" : 37), "HashListIterator::getRow()");
            assertEq(qi.first(), True, "HashListIterator::first()");
            assertEq(qi.last(), False, "HashListIterator::last()");
            assertEq(qi.index(), 0, "HashListIterator::index()");
            assertEq(qi.max(), 5, "HashListIterator::max()");
            assertEq(qi.name, "david", "HashListIterator::memberGate()");
            break;
        }

        HashListReverseIterator rqi(q);
        while (rqi.next()) {
            assertEq(rqi.getRow(), ("name" : "isabella", "age" : 1), "HashListReverseIterator::getRow()");
            assertEq(rqi.first(), True, "HashListReverseIterator::first()");
            assertEq(rqi.last(), False, "HashListReverseIterator::last()");
            assertEq(rqi.index(), 4, "HashListReverseIterator::index()");
            assertEq(rqi.max(), 5, "HashListReverseIterator::max()");
            assertEq(rqi.name, "isabella", "HashListReverseIterator::memberGate()");
            break;
        }

        # convert the hash of lists to a list of hashes
        qi.set(-1);
        list l = map qi.getRow(), qi;

        ListHashIterator lqi(l);
        while (lqi.next()) {
            assertEq(lqi.getRow(), ("name" : "david", "age" : 37), "ListHashIterator::getRow()");
            assertEq(lqi.first(), True, "ListHashIterator::first()");
            assertEq(lqi.last(), False, "ListHashIterator::last()");
            assertEq(lqi.index(), 0, "ListHashIterator::index()");
            assertEq(lqi.max(), 5, "ListHashIterator::max()");
            assertEq(lqi.name, "david", "ListHashIterator::memberGate()");

            ListHashIterator ni = lqi.copy();
            assertEq(ni.getRow(), ("name" : "david", "age" : 37), "ListHashIterator::getRow() (copy)");
            assertEq(ni.first(), True, "ListHashIterator::first() (copy)");
            assertEq(ni.index(), 0, "ListHashIterator::index() (copy)");
            break;
        }

        ListHashReverseIterator lrqi(l);
        while (lrqi.next()) {
            assertEq(lrqi.getRow(), ("name" : "isabella", "age" : 1), "ListHashReverseIterator::getRow()");
            assertEq(lrqi.first(), True, "ListHashReverseIterator::first()");
            assertEq(lrqi.last(), False, "ListHashReverseIterator::last()");
            assertEq(lrqi.index(), 4, "ListHashReverseIterator::index()");
            assertEq(lrqi.max(), 5, "ListHashReverseIterator::max()");
            assertEq(lrqi.name, "isabella", "ListHashReverseIterator::memberGate()");

            ListHashReverseIterator ni = lrqi.copy();
            assertEq(ni.getRow(), ("name" : "isabella", "age" : 1), "ListHashReverseIterator::getRow() (copy)");
            assertEq(ni.first(), True, "ListHashReverseIterator::first() (copy)");
            assertEq(ni.index(), 4, "ListHashReverseIterator::index() (copy)");
            break;
        }
    }
}

