/* ====================================================================
 * Copyright (c) 2003-2008  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 "WcStatus.h"
#include "WcEntry.h"
#include "Lock.h"


namespace svn
{

WcStatus::WcStatus() : _entry(NULL), _reposLock(NULL)
{
}
  
WcStatus::WcStatus( const sc::String& name, svn_wc_status2_t* status )
: _name(name), _entry(0), _lockStatus(WcStatusLock_None), _reposLock(0)
{
  if( status->entry )
  {
    _entry = new WcEntry( status->entry );
  }
  
  _textStatus = (WcStatusKind)status->text_status;
  _propStatus = (WcStatusKind)status->prop_status;

  _reposTextStatus = (WcStatusKind)status->repos_text_status;
  _reposPropStatus = (WcStatusKind)status->repos_prop_status;

  _locked   = 1 == status->locked;
  _copied   = 1 == status->copied;
  _switched = 1 == status->switched;

  if( status->repos_lock )
  {
    _reposLock = new Lock( status->repos_lock );
  }
}

WcStatus::WcStatus( const WcStatus& src )
: _entry(0), _reposLock(0)
{
  _name = src._name;

  if( src._entry )
  {
    _entry = new WcEntry( *(src._entry) );
  }

  _textStatus = src._textStatus;
  _propStatus = src._propStatus;

  _reposTextStatus = src._reposTextStatus;
  _reposPropStatus = src._reposPropStatus;

  _locked   = src._locked;
  _copied   = src._copied;
  _switched = src._switched;

  if( src._reposLock )
  {
    _reposLock = new Lock( *(src._reposLock) );
  }
}

WcStatus::~WcStatus()
{
  delete _entry;
  delete _reposLock;
}

void WcStatus::calcLockStatus( bool repos )
{
  if( repos )
  {
    if( _reposLock )
    {
      if( _entry && ! _entry->getLockToken().isEmpty() )
      {
        if( _reposLock->getToken() == _entry->getLockToken() )
        {
          _lockStatus = WcStatusLock_Locked;
        }
        else
        {
          _lockStatus = WcStatusLock_Stolen;
        }
      }
      else
      {
        _lockStatus = WcStatusLock_Other;
      }
    }
    else if( _entry && ! _entry->getLockToken().isEmpty() )
    {
      _lockStatus = WcStatusLock_Broken;
    }
    else
    {
      _lockStatus = WcStatusLock_None;
    }
  }
  else
  {
    if( _entry && ! _entry->getLockToken().isEmpty() )
    {
      _lockStatus = WcStatusLock_Locked;
    }
    else
    {
      _lockStatus = WcStatusLock_None;
    }
  }
}

const sc::String& WcStatus::getName() const
{
  return _name;
}

const sc::String& WcStatus::getUrl() const
{
  if( !_entry )
    return sc::NullString;

  return _entry->getUrl();
}

const WcEntry* WcStatus::getWcEntry() const
{
  return _entry;
}

WcStatusKind WcStatus::getTextStatus() const
{
  return _textStatus;
}

WcStatusKind WcStatus::getPropStatus() const
{
  return _propStatus;
}

bool WcStatus::isLocked() const
{
  return _locked;
}

bool WcStatus::isCopied() const
{
  return _copied;
}

bool WcStatus::isSwitched() const
{
  return _switched;
}

WcStatusKind WcStatus::getReposTextStatus() const
{
  return _reposTextStatus;
}

WcStatusKind WcStatus::getReposPropStatus() const
{
  return _reposPropStatus;
}

WcStatusLockKind WcStatus::getLockStatus() const
{
  return _lockStatus;
}

const Lock* WcStatus::getReposLock() const
{
  return _reposLock;
}

/**
 * \return true if text or property is changed otherwise false.
 */
bool WcStatus::isChanged() const
{
  return
    (_textStatus != WcStatus_Normal && _textStatus != WcStatus_None && _textStatus != WcStatus_Ignored) ||
    (_propStatus != WcStatus_Normal && _propStatus != WcStatus_None);
}

bool WcStatus::isReposChanged() const
{
  return
    (_reposTextStatus != WcStatus_Normal && _reposTextStatus != WcStatus_None) ||
    (_reposPropStatus != WcStatus_Normal && _reposPropStatus != WcStatus_None);
}

/**
 * \return true if text/property wc or repos is changed or if any of
 * the copied or switched flags is set (the wc locked flag is left out
 * intentionally. It is not *that* interesting). Otherwise false.
 */
bool WcStatus::isChangedOrFlaged() const
{
  return
       isChanged() || isReposChanged()
    || _switched   || _copied
    || _lockStatus != WcStatusLock_None;
}

bool WcStatus::isAddable() const
{
  return _textStatus == svn::WcStatus_Unversioned;
}

bool WcStatus::isRevertable() const
{
  return
    (_textStatus != svn::WcStatus_Normal && _textStatus != svn::WcStatus_Unversioned ) ||
    (_propStatus != svn::WcStatus_Normal && _propStatus != svn::WcStatus_None        );
}

bool WcStatus::isRemoveable() const
{
  return true;
}

bool WcStatus::isConflicted() const
{
  return _textStatus == svn::WcStatus_Conflicted;
}

bool WcStatus::isPropConflicted() const
{
  return _propStatus == svn::WcStatus_Conflicted;
}

bool WcStatus::isVersioned() const
{
  return _textStatus != svn::WcStatus_Unversioned;
}

bool WcStatus::isIgnored() const
{
  return _textStatus == svn::WcStatus_Ignored;
}

bool WcStatus::isDir() const
{
  if( ! _entry )
  {
    return false;
  }

  return _entry->isDir();
}
  
WcStatus* WcStatus::cloneSwitched()
{
  WcStatus* clone = new WcStatus(*this);
  clone->_switched = true;
  return clone;
}


} // namespace

