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

#ifndef _SC_WCMODEL_H
#define _SC_WCMODEL_H

// sc
#include "BaseModel.h"
#include "WcStatusCache.h"
#include "StatusResult.h"
#include "util/String.h"
#include "svn/svn.h"
#include "svn/ClientTypes.h"
#include "svn/WcStatusTypes.h"
class CmdResultCallback;
class AddParam;
class CommitParam;
class DeleteParam;
class DiffParam;
class EditConflictParam;
class MkdirParam;
class PropGetParam;
class PropListParam;
class PropSetParam;
class ResolvedParam;
class RevertParam;
class StatusParam;
class UpdateParam;
class CleanupParam;
class ScModel;
class Project;
class ScCmd;

// sys
#include <map>

namespace svn
{
  class Revision;
}


class WcModel : public BaseModel, public StatusResult
{
public:
  typedef std::map<sc::String,svn::WcStatusPtr> MapStatus;

  WcModel( ScModel* model );

  void setProject( const Project* prj );
  const Project* getProject() const;

  void setRoot( long wcId, const sc::String& rootPath );
  const sc::String& getRootPath() const;
  const sc::String& getRootUrl() const;
  long getWcId() const;

  void setCurrentPath( const sc::String& currPath );
  const sc::String& getCurrentPath() const;
  const sc::String& getCurrentUrl() const;
  sc::String getParentPath();

  void addStatus( const svn::WcStatuss& statussNew );
  void setSelection( const svn::WcStatuss& statussSel );

  const MapStatus& getAllStatus() const;
  const MapStatus& getModStatus() const;
  const MapStatus& getNewStatus() const;

  void getSelection( svn::Paths& paths ) const;
  void getSelection( svn::WcStatuss& statuss ) const;

  void add( AddParam*, CmdResultCallback* );
  void revert( RevertParam*, CmdResultCallback* );
  void commit( CommitParam*, CmdResultCallback* );
  void mkdir( MkdirParam*, CmdResultCallback* );
  void status( StatusParam*, CmdResultCallback* );
  void update( UpdateParam*, CmdResultCallback* );
  void edit( EditConflictParam*, CmdResultCallback* );
  void resolved( ResolvedParam*, CmdResultCallback* );
  void remove( DeleteParam*, CmdResultCallback* );
  void cleanup( CleanupParam*, CmdResultCallback* );

  void proplist( PropListParam*, CmdResultCallback*, bool async = true );
  void propset( PropSetParam*, CmdResultCallback*, bool async = true );
  void propget( PropGetParam*, CmdResultCallback*, bool async = true );

  void copy2( const sc::String& dst, CmdResultCallback* );

  void diffBaseWorking( CmdResultCallback* );
  void remove( const svn::Paths& unversioned );

  /** TODO move to specifications */

  /** all selected items are addable? */
  bool isAddable();
  /** all selected iems are revertable? */
  bool isRevertable();
  /** the selected item is diffable? */
  bool isDiffable();
  /** all selected items are commitable? */
  bool isCommitable();
  /** the selected item has is in conflict? */
  bool isConflicted();
  /** the selected item has property conflict? */
  bool isPropConflicted();
  /** all selected items are removeable? */
  bool isRemoveable();
  /** the selected item is moveable? obsolete?? */
  bool isMoveable();
  /** the selected item is versioned? */
  bool isVersioned();
  /** all selected items are versioned? */
  bool isVersionedAll();
  /** all selected items are unversioned? */
  bool isUnversionedAll();
  /** the selected item is a versioned directory? */
  bool isVersionedDir();
  /** the selected item is a versioned file? */
  bool isVersionedFile();

  bool getStatusAll() const;
  bool getStatusUpdates() const;
  bool getStatusIgnored() const;
  bool getStatusRecurse() const;

  /**
   * model kind.
   */
  bool isRepository() const;
  bool isWorkingCopy() const;

  struct Version
  {
    svn::Revnumber lowest;
    svn::Revnumber highest;
    bool           switched;
    bool           modified;
  };

  // svnversion
  Version getVersion();

  /**
   * check if path is a working copy.
   */
  bool isWorkingCopy( const sc::String& path );

  // StatusResult
  void setWcStatus( const sc::String& path, const svn::WcStatuss& statuss );
  bool getWcStatus( const sc::String& path, svn::WcStatuss& statuss );

  void update( const sc::String& root, const svn::WcStatuss& statuss );

private:
  bool isRevertable( svn::WcStatusPtr status );
  void updateVersion();
  void reset();

  const Project*    _prj;             ///< our project
  long              _wcId;            ///< unique wc id
  sc::String        _rootPath;        ///< our wc root path
  sc::String        _currPath;        ///< out current wc path

  MapStatus         _statussAll;      ///< all statuss.
  MapStatus         _statussMod;      ///< status of all modified folders.
  MapStatus         _statussNew;      ///< all new statuss.
  Version           _version;

  svn::WcStatuss    _statussSel;      ///< all currently selected status.

  WcStatusCache     _cache;
};

#endif //  _SC_WCMODEL_H
