/* ====================================================================
 * Copyright (c) 2009  Martin Hauner
 *                     http://subcommander.tigris.org
 *
 * Subcommander is licensed as described in the file doc/COPYING, which
 * you should have received as part of this distribution.
 * ====================================================================
 */

// gmock
#include <gmock/gmock.h>
using testing::_;
using testing::NiceMock;
using testing::InSequence;

// sc
#include "subcommander/wcview/ItemFolder.h"
#include "subcommander-test/WcViewItemTest.h" 
#include "util-test/Link.h"
EXPORT_TESTCASE(ASingleItemFolder);

// boost
#include <boost/tuple/tuple.hpp>

namespace wcview
{

class ASingleItemFolder : public ::testing::Test
{
protected:
  void SetUp()
  {
    _rootItem = createItem("invisible/root",
      WcViewItemTypeDir,WcViewItemStateNormal);


    _rootFolder = new ItemFolder(_rootItem, NULL);
  }

  void TearDown()
  {
    delete _rootFolder;
  }

  WcViewItemPtr createSingleChildViewItem ()
  {
    return createItem("invisible/root/ChildFileA",
      WcViewItemTypeFile,WcViewItemStateNormal);
  }

  typedef
    boost::tuples::tuple<WcViewItemPtr, WcViewItemPtr> 
    WcViewItemPtrTuple2;

  WcViewItemPtrTuple2 createChildViewItems ()
  {
    return boost::tuples::make_tuple(
      createItem("invisible/root/fileA",
        WcViewItemTypeFile,WcViewItemStateNormal),
      createItem("invisible/root/fileB",
        WcViewItemTypeFile,WcViewItemStateNormal)
      );
  }

protected:
  Item*         _rootFolder;
  WcViewItemPtr _rootItem;
};


TEST_F (ASingleItemFolder,shouldHaveNoChildsInitially)
{
  EXPECT_EQ ((wcview::Index)0, _rootFolder->getChildCount ());
}

TEST_F (ASingleItemFolder,shouldHaveNoParentIfItIsTheRootItem)
{
  EXPECT_EQ ( (Item*)NULL, _rootFolder->getParent());
}

TEST_F (ASingleItemFolder,shouldHaveAParent)
{
  ItemFolder item (createSingleChildViewItem (),_rootFolder);
  EXPECT_EQ (_rootFolder, item.getParent());
}

TEST_F (ASingleItemFolder,shouldThrowOnAccessWithBadIndex)
{
  try {
    _rootFolder->getChild (2);
    FAIL ();
  } catch (const BadIndexException& e) {
    EXPECT_EQ ((Index)2, e.getBadIndex());
  }
}

TEST_F (ASingleItemFolder,shouldHaveAName)
{
  EXPECT_EQ (_rootItem->path(),_rootFolder->getName());
}

TEST_F (ASingleItemFolder,shouldHaveAViewItem)
{
  EXPECT_EQ ( _rootItem, _rootFolder->getViewItem());
}

TEST_F (ASingleItemFolder,shouldIncreaseChildCountWhenAddingAChildItem)
{
  Item* child = new ItemFolder (createSingleChildViewItem(),_rootFolder);
  _rootFolder->insertChild (child);
  EXPECT_EQ ((wcview::Index)1,_rootFolder->getChildCount ());
  delete child;
}

TEST_F (ASingleItemFolder,shouldReturnChildItemsByIndex)
{
  WcViewItemPtrTuple2 tuple = createChildViewItems ();
  Item* childA = new ItemFolder (tuple.get<0>(),_rootFolder);
  Item* childB = new ItemFolder (tuple.get<1>(),_rootFolder);
  _rootFolder->insertChild (childA);
  _rootFolder->insertChild (childB);
  EXPECT_EQ (childA, _rootFolder->getChild(0));
  EXPECT_EQ (childB, _rootFolder->getChild(1));
  delete childA;
  delete childB;
}

TEST_F (ASingleItemFolder,shouldReturnChildItemsByName)
{
  WcViewItemPtrTuple2 tuple = createChildViewItems ();
  Item* childA = new ItemFolder (tuple.get<0>(),_rootFolder);
  Item* childB = new ItemFolder (tuple.get<1>(),_rootFolder);
  _rootFolder->insertChild (childA);
  _rootFolder->insertChild (childB);
  EXPECT_EQ (childA, _rootFolder->getChild (tuple.get<0>()->path ()));
  EXPECT_EQ (childB, _rootFolder->getChild (tuple.get<1>()->path ()));
  delete childA;
  delete childB;
}

TEST_F (ASingleItemFolder,shouldReturnAnIndexByName)
{
  WcViewItemPtrTuple2 tuple = createChildViewItems ();
  Item* childA = new ItemFolder (tuple.get<0>(),_rootFolder);
  Item* childB = new ItemFolder (tuple.get<1>(),_rootFolder);
  _rootFolder->insertChild (childA);
  _rootFolder->insertChild (childB);
  EXPECT_EQ (0,_rootFolder->getChildIndex (childA->getName ()));
  EXPECT_EQ (1,_rootFolder->getChildIndex (childB->getName ()));
  delete childA;
  delete childB;
}

TEST_F (ASingleItemFolder,shouldReturnZeroIndexIfItIsTheRootItem)
{
  EXPECT_EQ (0,_rootFolder->getParentIndex ());
}

TEST_F (ASingleItemFolder,shouldReturnTheIndexBelowItsParent)
{
  WcViewItemPtrTuple2 tuple = createChildViewItems ();
  Item* childA = new ItemFolder (tuple.get<0>(),_rootFolder);
  Item* childB = new ItemFolder (tuple.get<1>(),_rootFolder);
  _rootFolder->insertChild (childA);
  _rootFolder->insertChild (childB);
  EXPECT_EQ (0,childA->getParentIndex ());
  EXPECT_EQ (1,childB->getParentIndex ());
  delete childA;
  delete childB;
}

TEST_F (ASingleItemFolder,shouldThrowWhenAskedForIndexByBadName)
{
  sc::String badName ("hamwanicht");
  try {
    _rootFolder->getChildIndex (badName);
    FAIL ();
  } catch (const BadNameException& e) {
    EXPECT_EQ (badName, e.getBadName ());
  }
}

TEST_F (ASingleItemFolder,shouldThrowWhenAskedForItemByBadName)
{
  sc::String badName ("hamwanicht");
  try {
    _rootFolder->getChild (badName);
    FAIL ();
  } catch (const BadNameException& e) {
    EXPECT_EQ (badName, e.getBadName ());
  }
}

TEST_F (ASingleItemFolder,shouldThrowWhenAskedForItemByBadIndex)
{
  wcview::Index idx = 10;
  try {
    _rootFolder->getChild (idx);
    FAIL ();
  } catch (const BadIndexException& e) {
    EXPECT_EQ (idx, e.getBadIndex ());
  }
}


} // namespace
