/* ====================================================================
 * 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/ItemModel.h"
#include "subcommander/BadItemException.h"
#include "subcommander-test/WcViewItemTest.h" 
#include "subcommander-test/MockSignalTarget.h"
#include "subcommander-test/IndexEq.h"
#include "sublib/OStreamQt.h"
#include "util-test/Link.h"
EXPORT_TESTCASE(AddingItemsToAModel);

namespace wcview
{

class AddingItemsToAModel : public ::testing::Test
{
protected:
  void SetUp()
  {
    _data = new WcViewItemDataTest();
    _model = new ItemModel( sc::String("invisible/root"), _data );

    _root = createItem("invisible/root",
      WcViewItemTypeDir,WcViewItemStateNormal);
    _fileA = createItem("invisible/root/fileA",
      WcViewItemTypeFile,WcViewItemStateNormal);
    _fileB = createItem("invisible/root/fileB",
      WcViewItemTypeFile,WcViewItemStateNormal);
    _folderC = createItem("invisible/root/folderC",
      WcViewItemTypeDir,WcViewItemStateNormal);
    _fileD = createItem("invisible/root/folderC/fileD",
      WcViewItemTypeFile,WcViewItemStateNormal);

    _bad = createItem("invisible/root/badfolder/bad",
      WcViewItemTypeFile,WcViewItemStateNormal);
  }

  void TearDown()
  {
    delete _model;
    delete _data;
  }

protected:
  WcViewItemDataTest* _data;
  ItemModel*          _model;

  WcViewItemPtr       _root;
  WcViewItemPtr       _fileA;
  WcViewItemPtr       _fileB;
  WcViewItemPtr       _folderC;
  WcViewItemPtr       _fileD;

  WcViewItemPtr       _bad;
};


TEST_F (AddingItemsToAModel, shouldEmitRowsInsertedSignalsForRootItem)
{
  MockSignalTarget mtarget(_model);
  {
    InSequence dummy;
    EXPECT_CALL(mtarget, rowsAboutToBeInserted(
      IndexEq(-1,-1),0,0)).Times(1);
    EXPECT_CALL(mtarget, rowsInserted(
      IndexEq(-1,-1),0,0)).Times(1);
  }
  _model->insert (_root);
}

TEST_F (AddingItemsToAModel, shouldEmitRowsInsertedSignalsForAllItems)
{
  MockSignalTarget mtarget(_model);
  {
    InSequence dummy;
    EXPECT_CALL(mtarget, rowsAboutToBeInserted (IndexEq (-1,-1),0,0));
    EXPECT_CALL(mtarget, rowsInserted (IndexEq (-1,-1),0,0));

    EXPECT_CALL(mtarget, rowsAboutToBeInserted (IndexEq (0,0),0,0));
    EXPECT_CALL(mtarget, rowsInserted( IndexEq (0,0),0,0));

    EXPECT_CALL(mtarget, rowsAboutToBeInserted (IndexEq (0,0),1,1));
    EXPECT_CALL(mtarget, rowsInserted (IndexEq (0,0),1,1));

    EXPECT_CALL(mtarget, rowsAboutToBeInserted (IndexEq (0,0),2,2));
    EXPECT_CALL(mtarget, rowsInserted (IndexEq (0,0),2,2));

    EXPECT_CALL(mtarget, rowsAboutToBeInserted (IndexEq (2,0),0,0));
    EXPECT_CALL(mtarget, rowsInserted (IndexEq (2,0),0,0));
  }
  _model->insert (_root);
  _model->insert (_fileA);
  _model->insert (_fileB);
  _model->insert (_folderC);
  _model->insert (_fileD);
}

TEST_F (AddingItemsToAModel, shouldEmitRowsInsertedSignalsForAllItems2)
{
  MockSignalTarget mtarget(_model);

  EXPECT_CALL(mtarget, rowsAboutToBeInserted (_,_,_)).Times (4);
  EXPECT_CALL(mtarget, rowsInserted (_,_,_)).Times (4);
  {
    InSequence dummy;
    EXPECT_CALL(mtarget, rowsAboutToBeInserted (IndexEq (2,0),0,0));
    EXPECT_CALL(mtarget, rowsInserted (IndexEq (2,0),0,0));
  }
  _model->insert (_root);
  _model->insert (_fileA);
  _model->insert (_fileB);
  _model->insert (_folderC);
  _model->insert (_fileD);
}


TEST_F (AddingItemsToAModel,shouldCreateValidChildIndex)
{
  // root/fileA
  _model->insert (_root);
  _model->insert (_fileA);

  QModelIndex root  = _model->index (0,0,QModelIndex());
  QModelIndex fileA = root.child(0,0);
  EXPECT_EQ ( 0, fileA.row() );
  EXPECT_EQ ( 0, fileA.column() );
  EXPECT_EQ ( root, fileA.parent() );
}

TEST_F (AddingItemsToAModel,shouldThrowOnBadItem)
{
  _model->insert (_root);
  _model->insert (_fileA);
  _model->insert (_fileB);
  _model->insert (_folderC);
  _model->insert (_fileD);

  EXPECT_THROW (_model->insert (_bad), BadItemException );
}


} // namespace
