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

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

%requires ../../../../qlib/QUnit.qm
%requires ../../../../qlib/DataProvider
%requires ../../../../qlib/FixedLengthUtil

%exec-class Test

class Test inherits QUnit::Test {
    public {
        const Data = "11111bb\ncddd31122014\n\n\n22222gg\n";

        const Specs = (
            "type1" : (
                "col1" : (
                    "length" : 5,
                    "type"   : "int",
                ),
                "col2" : (
                    "length" : 2,
                    "type"   : "string",
                ),
            ),
            "type2" : (
                "col3" : (
                    "length" : 1,
                    "type"   : "string",
                ),
                "col4" : (
                    "length" : 3,
                    "type"   : "string",
                ),
                "col5" : (
                    "length"   : 8,
                    "type"     : "date",
                    "format"   : "DDMMYYYY",
                    # "timezone" : "UTC", # use global if omitted
                ),
            ),
            );

        const GlobalOptions = (
            "encoding"     : "UTF-8",
            "eol"          : "\n",
            "ignore_empty" : True,
            "timezone"     : "UTC", # used if not in some date column specification
            );
    }

    constructor() : QUnit::Test("transition_check_iterator", "1.0", \ARGV) {
        addTestCase("transition check", \check());
        set_return_value(main());
    }

    check() {
        MyFixedLengthDataIterator1 i(Data, Specs, GlobalOptions);
        testAssertionValue("line 1 is there", i.next(), True);
        testAssertionValue("line 1 content check", i.getValue(), ("type": "type1", "record": ("col1" : 11111, "col2" : "bb")));
        testAssertionValue("line 2 is there", i.next(), True);
        testAssertionValue("line 2 content check", i.getValue(), ("type": "type2", "record": ("col3" : "c", "col4" : "ddd", "col5" : 2014-12-31Z)));
        testAssertionValue("line 3 is there", i.next(), True);
        testAssertionValue("line 3 content check", i.getValue(), ("type": "type1", "record": ("col1" : 22222, "col2" : "gg")));
        testAssertionValue("line 4 is not there", i.next(), False);

        MyFixedLengthDataIterator2 j(Data, Specs, GlobalOptions);
        testAssertionValue("line 1 is there", j.next(), True);
        testAssertionValue("line 1 content check", j.getValue(), ("type": "type1", "record": ("col1" : 11111, "col2" : "bb")));
        testAssertionValue("line 2 is there", j.next(), True);
        testAssertionValue("line 2 content check", j.getValue(), ("type": "type2", "record": ("col3" : "c", "col4" : "ddd", "col5" : 2014-12-31Z)));
        testAssertionValue("line 3 is there", j.next(), True);
        code wr = sub (MyFixedLengthDataIterator2 k) {
            k.getValue();
        };
        testAssertion("State type1 cannot follow state type1 for line 22222gg", wr, j, new TestResultExceptionType("FIXED-LENGTH-UTIL-INVALID-TRANSITION"));
    }
}

public class MyFixedLengthDataIterator1 inherits FixedLengthUtil::FixedLengthDataIterator {
    constructor(string d, hash h, *hash g) : FixedLengthUtil::FixedLengthDataIterator(d, h, g) {
    }

    bool checkTransition(*string from, *string to) {
        if ((from == "type1" && to == "type2")
            || (from == NOTHING && to == "type1")
            || (from == "type2" && to == "type1")) {
            return True;
        }

        return False;
    }
}

public class MyFixedLengthDataIterator2 inherits FixedLengthUtil::FixedLengthDataIterator {
    constructor(string d, hash h, *hash g) : FixedLengthUtil::FixedLengthDataIterator(d, h, g) {
    }

    bool checkTransition(*string from, *string to) {
        if ((from == "type1" && to == "type2")
            || (from == NOTHING && to == "type1")) {
            return True;
        }

        return False;
    }
}
