/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkRandom.h"
#include "SkTInternalLList.h"
#include "SkTLList.h"
#include "Test.h"

class ListElement {
public:
    ListElement(int id) : fID(id) {
    }
    bool operator== (const ListElement& other) { return fID == other.fID; }

#if SK_ENABLE_INST_COUNT
    // Make the instance count available publicly.
    static int InstanceCount() { return GetInstanceCount(); }
#endif

    int fID;

private:
    SK_DECLARE_INST_COUNT_ROOT(ListElement);
    SK_DECLARE_INTERNAL_LLIST_INTERFACE(ListElement);
};

static void check_list(const SkTInternalLList<ListElement>& list,
                       skiatest::Reporter* reporter,
                       bool empty,
                       int numElements,
                       bool in0, bool in1, bool in2, bool in3,
                       ListElement elements[4]) {

    REPORTER_ASSERT(reporter, empty == list.isEmpty());
#ifdef SK_DEBUG
    list.validate();
    REPORTER_ASSERT(reporter, numElements == list.countEntries());
    REPORTER_ASSERT(reporter, in0 == list.isInList(&elements[0]));
    REPORTER_ASSERT(reporter, in1 == list.isInList(&elements[1]));
    REPORTER_ASSERT(reporter, in2 == list.isInList(&elements[2]));
    REPORTER_ASSERT(reporter, in3 == list.isInList(&elements[3]));
#endif
}

static void TestTInternalLList(skiatest::Reporter* reporter) {
    SkTInternalLList<ListElement> list;
    ListElement elements[4] = {
        ListElement(0),
        ListElement(1),
        ListElement(2),
        ListElement(3),
    };

    // list should be empty to start with
    check_list(list, reporter, true, 0, false, false, false, false, elements);

    list.addToHead(&elements[0]);

    check_list(list, reporter, false, 1, true, false, false, false, elements);

    list.addToHead(&elements[1]);
    list.addToHead(&elements[2]);
    list.addToHead(&elements[3]);

    check_list(list, reporter, false, 4, true, true, true, true, elements);

    // test out iterators
    typedef SkTInternalLList<ListElement>::Iter Iter;
    Iter iter;

    ListElement* cur = iter.init(list, Iter::kHead_IterStart);
    for (int i = 0; NULL != cur; ++i, cur = iter.next()) {
        REPORTER_ASSERT(reporter, cur->fID == 3-i);
    }

    cur = iter.init(list, Iter::kTail_IterStart);
    for (int i = 0; NULL != cur; ++i, cur = iter.prev()) {
        REPORTER_ASSERT(reporter, cur->fID == i);
    }

    // remove middle, frontmost then backmost
    list.remove(&elements[1]);
    list.remove(&elements[3]);
    list.remove(&elements[0]);

    check_list(list, reporter, false, 1, false, false, true, false, elements);

    // remove last element
    list.remove(&elements[2]);

    // list should be empty again
    check_list(list, reporter, true, 0, false, false, false, false, elements);

    // test out methods that add to the middle of the list.
    list.addAfter(&elements[1], NULL);
    check_list(list, reporter, false, 1, false, true, false, false, elements);

    list.remove(&elements[1]);

    list.addBefore(&elements[1], NULL);
    check_list(list, reporter, false, 1, false, true, false, false, elements);

    list.addBefore(&elements[0], &elements[1]);
    check_list(list, reporter, false, 2, true, true, false, false, elements);

    list.addAfter(&elements[3], &elements[1]);
    check_list(list, reporter, false, 3, true, true, false, true, elements);

    list.addBefore(&elements[2], &elements[3]);
    check_list(list, reporter, false, 4, true, true, true, true, elements);

    cur = iter.init(list, Iter::kHead_IterStart);
    for (int i = 0; NULL != cur; ++i, cur = iter.next()) {
        REPORTER_ASSERT(reporter, cur->fID == i);
    }
}

static void TestTLList(skiatest::Reporter* reporter) {
    typedef SkTLList<ListElement> ElList;
    typedef ElList::Iter Iter;
    SkRandom random;

    for (int i = 1; i <= 16; i *= 2) {

        ElList list1(i);
        ElList list2(i);
        Iter iter1;
        Iter iter2;
        Iter iter3;
        Iter iter4;

#if SK_ENABLE_INST_COUNT
        SkASSERT(0 == ListElement::InstanceCount());
#endif

        REPORTER_ASSERT(reporter, list1.isEmpty());
        REPORTER_ASSERT(reporter, NULL == iter1.init(list1, Iter::kHead_IterStart));
        REPORTER_ASSERT(reporter, NULL == iter1.init(list1, Iter::kTail_IterStart));
        // Try popping an empty list
        list1.popHead();
        list1.popTail();
        REPORTER_ASSERT(reporter, list1.isEmpty());
        REPORTER_ASSERT(reporter, list1 == list2);

        // Create two identical lists, one by appending to head and the other to the tail.
        list1.addToHead(ListElement(1));
        list2.addToTail(ListElement(1));
#if SK_ENABLE_INST_COUNT
        SkASSERT(2 == ListElement::InstanceCount());
#endif
        iter1.init(list1, Iter::kHead_IterStart);
        iter2.init(list1, Iter::kTail_IterStart);
        REPORTER_ASSERT(reporter, iter1.get()->fID == iter2.get()->fID);
        iter3.init(list2, Iter::kHead_IterStart);
        iter4.init(list2, Iter::kTail_IterStart);
        REPORTER_ASSERT(reporter, iter3.get()->fID == iter1.get()->fID);
        REPORTER_ASSERT(reporter, iter4.get()->fID == iter1.get()->fID);
        REPORTER_ASSERT(reporter, list1 == list2);

        list2.reset();

        // use both before/after in-place construction on an empty list
        SkNEW_INSERT_IN_LLIST_BEFORE(&list2, list2.headIter(), ListElement, (1));
        REPORTER_ASSERT(reporter, list2 == list1);
        list2.reset();

        SkNEW_INSERT_IN_LLIST_AFTER(&list2, list2.tailIter(), ListElement, (1));
        REPORTER_ASSERT(reporter, list2 == list1);

        // add an element to the second list, check that iters are still valid
        iter3.init(list2, Iter::kHead_IterStart);
        iter4.init(list2, Iter::kTail_IterStart);
        list2.addToHead(ListElement(2));

#if SK_ENABLE_INST_COUNT
        SkASSERT(3 == ListElement::InstanceCount());
#endif

        REPORTER_ASSERT(reporter, iter3.get()->fID == iter1.get()->fID);
        REPORTER_ASSERT(reporter, iter4.get()->fID == iter1.get()->fID);
        REPORTER_ASSERT(reporter, 1 == Iter(list2, Iter::kTail_IterStart).get()->fID);
        REPORTER_ASSERT(reporter, 2 == Iter(list2, Iter::kHead_IterStart).get()->fID);
        REPORTER_ASSERT(reporter, list1 != list2);
        list1.addToHead(ListElement(2));
        REPORTER_ASSERT(reporter, list1 == list2);
#if SK_ENABLE_INST_COUNT
        SkASSERT(4 == ListElement::InstanceCount());
#endif
        REPORTER_ASSERT(reporter, !list1.isEmpty());

        list1.reset();
        list2.reset();
#if SK_ENABLE_INST_COUNT
        SkASSERT(0 == ListElement::InstanceCount());
#endif
        REPORTER_ASSERT(reporter, list1.isEmpty() && list2.isEmpty());

        // randomly perform insertions and deletions on a list and perform tests
        int count = 0;
        for (int j = 0; j < 100; ++j) {
            if (list1.isEmpty() || random.nextBiasedBool(3  * SK_Scalar1 / 4)) {
                int id = j;
                // Choose one of three ways to insert a new element: at the head, at the tail,
                // before a random element, after a random element
                int numValidMethods = 0 == count ? 2 : 4;
                int insertionMethod = random.nextULessThan(numValidMethods);
                switch (insertionMethod) {
                    case 0:
                        list1.addToHead(ListElement(id));
                        break;
                    case 1:
                        list1.addToTail(ListElement(id));
                        break;
                    case 2: // fallthru to share code that picks random element.
                    case 3: {
                        int n = random.nextULessThan(list1.count());
                        Iter iter = list1.headIter();
                        // remember the elements before/after the insertion point.
                        while (n--) {
                            iter.next();
                        }
                        Iter prev(iter);
                        Iter next(iter);
                        next.next();
                        prev.prev();

                        SkASSERT(NULL != iter.get());
                        // insert either before or after the iterator, then check that the
                        // surrounding sequence is correct.
                        if (2 == insertionMethod) {
                            SkNEW_INSERT_IN_LLIST_BEFORE(&list1, iter, ListElement, (id));
                            Iter newItem(iter);
                            newItem.prev();
                            REPORTER_ASSERT(reporter, newItem.get()->fID == id);

                            if (NULL != next.get()) {
                                REPORTER_ASSERT(reporter, next.prev()->fID == iter.get()->fID);
                            }
                            if (NULL != prev.get()) {
                                REPORTER_ASSERT(reporter, prev.next()->fID == id);
                            }
                        } else {
                            SkNEW_INSERT_IN_LLIST_AFTER(&list1, iter, ListElement, (id));
                            Iter newItem(iter);
                            newItem.next();
                            REPORTER_ASSERT(reporter, newItem.get()->fID == id);

                            if (NULL != next.get()) {
                                REPORTER_ASSERT(reporter, next.prev()->fID == id);
                            }
                            if (NULL != prev.get()) {
                                REPORTER_ASSERT(reporter, prev.next()->fID == iter.get()->fID);
                            }
                        }
                    }
                }
                ++count;
            } else {
                // walk to a random place either forward or backwards and remove.
                int n = random.nextULessThan(list1.count());
                Iter::IterStart start;
                ListElement* (Iter::*incrFunc)();

                if (random.nextBool()) {
                    start = Iter::kHead_IterStart;
                    incrFunc = &Iter::next;
                } else {
                    start = Iter::kTail_IterStart;
                    incrFunc = &Iter::prev;
                }

                // find the element
                Iter iter(list1, start);
                while (n--) {
                    REPORTER_ASSERT(reporter, NULL != iter.get());
                    (iter.*incrFunc)();
                }
                REPORTER_ASSERT(reporter, NULL != iter.get());

                // remember the prev and next elements from the element to be removed
                Iter prev = iter;
                Iter next = iter;
                prev.prev();
                next.next();
                list1.remove(iter.get());

                // make sure the remembered next/prev iters still work
                Iter pn = prev; pn.next();
                Iter np = next; np.prev();
                // pn should match next unless the target node was the head, in which case prev
                // walked off the list.
                REPORTER_ASSERT(reporter, pn.get() == next.get() || NULL == prev.get());
                // Similarly, np should match prev unless next originally walked off the tail.
                REPORTER_ASSERT(reporter, np.get() == prev.get() || NULL == next.get());
                --count;
            }
            REPORTER_ASSERT(reporter, count == list1.count());
#if SK_ENABLE_INST_COUNT
            SkASSERT(count == ListElement::InstanceCount());
#endif
        }
        list1.reset();
#if SK_ENABLE_INST_COUNT
        SkASSERT(0 == ListElement::InstanceCount());
#endif
    }
}

DEF_TEST(LList, reporter) {
    TestTInternalLList(reporter);
    TestTLList(reporter);
}
