/* ====================================================================
 * Copyright (c) 2003-2007, 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.
 * ====================================================================
 */

// sc
#include "RepositoryModel.h"
#include "ScModel.h"
#include "commands/ListCmd.h"
#include "commands/ListCmd2.h"
#include "commands/ListParam.h"
#include "commands/DetailsCmd.h"
#include "commands/DetailsParam.h"
#include "commands/DiffCmd.h"
#include "commands/DiffParam.h"
#include "commands/MkdirCmd.h"
#include "commands/MkdirParam.h"
#include "commands/SwitchCmd.h"
#include "commands/SwitchParam.h"
#include "commands/LogCmd.h"
#include "commands/PropListCmd.h"
#include "commands/ImportCmd.h"
#include "commands/MoveParam.h"
#include "commands/CopyParam.h"
#include "util/Guard.h"
#include "svn/Revision.h"
#include "svn/DirEntry.h"

// qt
#include <QtCore/QString>


RepositoryModel::RepositoryModel( ScModel* model ) : BaseModel(model), _prj(0)
{
}

void RepositoryModel::setRoot( long rpId, const sc::String& url )
{
  reset();

  _rpId    = rpId;

  _rootUrl = url;
  _currUrl = url;
}

sc::String RepositoryModel::getRootUrl() const
{
  return _rootUrl;
}

long RepositoryModel::getRpId() const
{
  return _rpId;
}

void RepositoryModel::setCurrentUrl( const sc::String& currUrl )
{
  _currUrl = currUrl;
}

const sc::String& RepositoryModel::getCurrentUrl() const
{
  return _currUrl;
}

void RepositoryModel::setCurrentEntry( svn::DirEntryPtr entry )
{
  _entriesAll.insert( MapEntry::value_type(entry->getName(),entry) );
}

sc::String RepositoryModel::getParentUrl() const
{
  if( _rootUrl == _currUrl )
  {
    return sc::NullString;
  }

  return sc::String( 
    QString::fromUtf8(_currUrl).section( '/', 0, -2 ).utf8() );
}

void RepositoryModel::setProject( Project* prj )
{
  _prj = prj;
}

Project* RepositoryModel::getProject() const
{
  return _prj;
}

const RepositoryModel::MapEntry& RepositoryModel::getAllEntries() const
{
  return _entriesAll;
}

const RepositoryModel::MapEntry& RepositoryModel::getNewEntries() const
{
  return _entriesNew;
}

void RepositoryModel::reset()
{
  _entriesAll.clear();
  _entriesSel.clear();
}

void RepositoryModel::addEntries( const svn::DirEntries& entriesNew )
{
  _entriesNew.clear();

  for( svn::DirEntries::const_iterator it = entriesNew.begin(); it != entriesNew.end(); it++ )
  {
    _entriesAll.insert( MapEntry::value_type((*it)->getName(),*it) );
  }

  update( _currUrl, entriesNew );
}

void RepositoryModel::setSelection( const svn::DirEntries& entriesSel )
{
  _entriesSel = entriesSel;
}

void RepositoryModel::getSelection( svn::Paths& paths ) const
{
  for( svn::DirEntries::const_iterator it = _entriesSel.begin(); it != _entriesSel.end(); it++ )
  {
    paths.push_back( (*it)->getName() );
  }
}

void RepositoryModel::getSelection( svn::DirEntries& entries ) const
{
  entries = _entriesSel;
}

bool RepositoryModel::isRepository() const
{
  return true;
}

bool RepositoryModel::isWorkingCopy() const
{
  return false;
}

void RepositoryModel::list( ListParam* param, CmdResultCallback* cb )
{
  //ListCmd* cmd = new ListCmd( param, cb );
  ListCmd2* cmd = new ListCmd2( param, _model->getListCache(), cb );
  _model->runAsync( cmd );
}

void RepositoryModel::switchx( SwitchParam* param, CmdResultCallback* cb )
{
  SwitchCmd* cmd   = new SwitchCmd( param, cb );
  _model->runAsync( cmd );
}

void RepositoryModel::mkdir( MkdirParam* param, CmdResultCallback* cb )
{
  MkdirCmd* cmd = new MkdirCmd( param, cb );
  _model->runAsync(cmd);
}

void RepositoryModel::proplist( PropListParam* param, CmdResultCallback* cb )
{
  PropListCmd* cmd = new PropListCmd( param, cb );
  _model->runAsync(cmd);
}

void RepositoryModel::details( DetailsParam* param, CmdResultCallback* cb )
{
  DetailsCmd* cmd = new DetailsCmd( param, cb );
  _model->runAsync(cmd);
}

void RepositoryModel::import( ImportParam* param, CmdResultCallback* cb )
{
  ImportCmd* cmd = new ImportCmd( param, cb );
  _model->runAsync(cmd);
}

void RepositoryModel::copy2( const sc::String& dst, CmdResultCallback* cb )
{
  svn::Paths paths;
  getSelection(paths);

  CopyParam* param = new CopyParam( paths, 
    svn::RevisionPtr(new svn::Revision(svn::Revision_Unspecified)), dst );

  copy( param, cb );
}

void RepositoryModel::update( const sc::String& root, const svn::DirEntries& entries )
{
  MapEntry::iterator itr = _entriesAll.find( root );
  if( itr != _entriesAll.end() )
  {
    svn::DirEntryPtr entry = (*itr).second;

    _entriesNew.insert( MapEntry::value_type(entry->getName(), entry) );
  }

  for( svn::DirEntries::const_iterator it = entries.begin(); it != entries.end(); it++ )
  {
    svn::DirEntryPtr entry = (*it);

    _entriesNew.insert( MapEntry::value_type(entry->getName(), entry) );
  }
}

bool RepositoryModel::isDir()
{
  if( _entriesSel.size() != 1 )
  {
    return false;
  }

  svn::DirEntryPtr entry = *(_entriesSel.begin());
  return entry->isDir();
}

bool RepositoryModel::isFile()
{
  if( _entriesSel.size() != 1 )
  {
    return false;
  }

  svn::DirEntryPtr entry = *(_entriesSel.begin());
  return entry->isFile();
}
