/*
 * Copyright (C) 2012 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */


#include "sky/engine/wtf/TreeNode.h"

#include <gtest/gtest.h>
#include "sky/engine/wtf/PassRefPtr.h"
#include "sky/engine/wtf/RefCounted.h"
#include "sky/engine/wtf/RefPtr.h"

namespace {

class TestTree : public RefCounted<TestTree>, public TreeNode<TestTree> {
public:
    static PassRefPtr<TestTree> create() { return adoptRef(new TestTree()); }
};

TEST(TreeNodeTest, AppendChild)
{
    RefPtr<TestTree> root = TestTree::create();
    RefPtr<TestTree> firstChild = TestTree::create();
    RefPtr<TestTree> lastChild = TestTree::create();

    root->appendChild(firstChild.get());
    EXPECT_EQ(root->firstChild(), firstChild.get());
    EXPECT_EQ(root->lastChild(), firstChild.get());
    EXPECT_EQ(firstChild->parent(), root.get());

    root->appendChild(lastChild.get());
    EXPECT_EQ(root->firstChild(), firstChild.get());
    EXPECT_EQ(root->lastChild(), lastChild.get());
    EXPECT_EQ(lastChild->previous(), firstChild.get());
    EXPECT_EQ(firstChild->next(), lastChild.get());
    EXPECT_EQ(lastChild->parent(), root.get());
}

TEST(TreeNodeTest, InsertBefore)
{
    RefPtr<TestTree> root = TestTree::create();
    RefPtr<TestTree> firstChild = TestTree::create();
    RefPtr<TestTree> middleChild = TestTree::create();
    RefPtr<TestTree> lastChild = TestTree::create();

    // Inserting single node
    root->insertBefore(lastChild.get(), 0);
    EXPECT_EQ(lastChild->parent(), root.get());
    EXPECT_EQ(root->firstChild(), lastChild.get());
    EXPECT_EQ(root->lastChild(), lastChild.get());

    // Then prepend
    root->insertBefore(firstChild.get(), lastChild.get());
    EXPECT_EQ(firstChild->parent(), root.get());
    EXPECT_EQ(root->firstChild(), firstChild.get());
    EXPECT_EQ(root->lastChild(), lastChild.get());
    EXPECT_EQ(firstChild->next(), lastChild.get());
    EXPECT_EQ(firstChild.get(), lastChild->previous());

    // Inserting in the middle
    root->insertBefore(middleChild.get(), lastChild.get());
    EXPECT_EQ(middleChild->parent(), root.get());
    EXPECT_EQ(root->firstChild(), firstChild.get());
    EXPECT_EQ(root->lastChild(), lastChild.get());
    EXPECT_EQ(middleChild->previous(), firstChild.get());
    EXPECT_EQ(middleChild->next(), lastChild.get());
    EXPECT_EQ(firstChild->next(), middleChild.get());
    EXPECT_EQ(lastChild->previous(), middleChild.get());

}

TEST(TreeNodeTest, RemoveSingle)
{
    RefPtr<TestTree> root = TestTree::create();
    RefPtr<TestTree> child = TestTree::create();
    RefPtr<TestTree> nullNode;

    root->appendChild(child.get());
    root->removeChild(child.get());
    EXPECT_EQ(child->next(), nullNode.get());
    EXPECT_EQ(child->previous(), nullNode.get());
    EXPECT_EQ(child->parent(), nullNode.get());
    EXPECT_EQ(root->firstChild(), nullNode.get());
    EXPECT_EQ(root->lastChild(), nullNode.get());
}

class Trio {
public:
    Trio()
        : root(TestTree::create())
        , firstChild(TestTree::create())
        , middleChild(TestTree::create())
        , lastChild(TestTree::create())
    {
    }

    void appendChildren()
    {
        root->appendChild(firstChild.get());
        root->appendChild(middleChild.get());
        root->appendChild(lastChild.get());
    }

    RefPtr<TestTree> root;
    RefPtr<TestTree> firstChild;
    RefPtr<TestTree> middleChild;
    RefPtr<TestTree> lastChild;
};

TEST(TreeNodeTest, RemoveMiddle)
{
    Trio trio;
    trio.appendChildren();

    trio.root->removeChild(trio.middleChild.get());
    EXPECT_TRUE(trio.middleChild->orphan());
    EXPECT_EQ(trio.firstChild->next(), trio.lastChild.get());
    EXPECT_EQ(trio.lastChild->previous(), trio.firstChild.get());
    EXPECT_EQ(trio.root->firstChild(), trio.firstChild.get());
    EXPECT_EQ(trio.root->lastChild(), trio.lastChild.get());
}

TEST(TreeNodeTest, RemoveLast)
{
    RefPtr<TestTree> nullNode;
    Trio trio;
    trio.appendChildren();

    trio.root->removeChild(trio.lastChild.get());
    EXPECT_TRUE(trio.lastChild->orphan());
    EXPECT_EQ(trio.middleChild->next(), nullNode.get());
    EXPECT_EQ(trio.root->firstChild(), trio.firstChild.get());
    EXPECT_EQ(trio.root->lastChild(), trio.middleChild.get());
}

TEST(TreeNodeTest, RemoveFirst)
{
    RefPtr<TestTree> nullNode;
    Trio trio;
    trio.appendChildren();

    trio.root->removeChild(trio.firstChild.get());
    EXPECT_TRUE(trio.firstChild->orphan());
    EXPECT_EQ(trio.middleChild->previous(), nullNode.get());
    EXPECT_EQ(trio.root->firstChild(), trio.middleChild.get());
    EXPECT_EQ(trio.root->lastChild(), trio.lastChild.get());
}

TEST(TreeNodeTest, TakeChildrenFrom)
{
    RefPtr<TestTree> newParent = TestTree::create();
    Trio trio;
    trio.appendChildren();

    newParent->takeChildrenFrom(trio.root.get());

    EXPECT_FALSE(trio.root->hasChildren());
    EXPECT_TRUE(newParent->hasChildren());
    EXPECT_EQ(trio.firstChild.get(), newParent->firstChild());
    EXPECT_EQ(trio.middleChild.get(), newParent->firstChild()->next());
    EXPECT_EQ(trio.lastChild.get(), newParent->lastChild());
}

class TrioWithGrandChild : public Trio {
public:
    TrioWithGrandChild()
        : grandChild(TestTree::create())
    {
    }

    void appendChildren()
    {
        Trio::appendChildren();
        middleChild->appendChild(grandChild.get());
    }

    RefPtr<TestTree> grandChild;
};

TEST(TreeNodeTest, TraverseNext)
{
    TrioWithGrandChild trio;
    trio.appendChildren();

    TestTree* order[] = {
        trio.root.get(), trio.firstChild.get(), trio.middleChild.get(),
        trio.grandChild.get(), trio.lastChild.get()
    };

    unsigned orderIndex = 0;
    for (TestTree* node = trio.root.get(); node; node = traverseNext(node), orderIndex++)
        EXPECT_EQ(node, order[orderIndex]);
    EXPECT_EQ(orderIndex, sizeof(order) / sizeof(TestTree*));
}

TEST(TreeNodeTest, TraverseNextPostORder)
{
    TrioWithGrandChild trio;
    trio.appendChildren();


    TestTree* order[] = {
        trio.firstChild.get(),
        trio.grandChild.get(), trio.middleChild.get(), trio.lastChild.get(), trio.root.get()
    };

    unsigned orderIndex = 0;
    for (TestTree* node = traverseFirstPostOrder(trio.root.get()); node; node = traverseNextPostOrder(node), orderIndex++)
        EXPECT_EQ(node, order[orderIndex]);
    EXPECT_EQ(orderIndex, sizeof(order) / sizeof(TestTree*));

}


} // namespace
