/* ====================================================================
 * Copyright (c) 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_WCVIEWMODEL_H
#define _SC_WCVIEWMODEL_H

// sc
#include "StatusResult.h"
#include "WcSelection.h"
#include "sublib/TargetId.h"
#include "svn/PropListItemTypes.h"
#include "svn/ClientTypes.h"
#include "svn/Revision.h"
class Bookmark;
class Project;
class ScModel;
class StatusParam;
class DiffParam;
class AddParam;
class MoveParam;
class UpdateParam;
class ExportParam;
class CopyParam;
class LockParam;
class UnlockParam;
class PropListParam;
class PropSetParam;
class PropGetParam;
class CommitParam;
class LogParam;
namespace sc {
  class Error;
}

// qt
#include <QtCore/QObject>

// sys
#include <map>


class Version
{
public:
  Version();
  Version( const Version& );

  Version operator+( const Version& );
  Version& operator+=( const Version& );
  QString toString() const;

  svn::Revnumber lowest;
  svn::Revnumber highest;
  bool           switched;
  bool           modified;
};

class DeepStatus
{
public:
  DeepStatus();
  bool operator==( const DeepStatus& );
  bool operator!=( const DeepStatus& );

  bool modified;
};

class StatusInfo
{
public:
  svn::WcStatuss statuss;
  Version        version;
  DeepStatus     status;
};

typedef std::map< sc::String, StatusInfo > Status;
typedef std::pair< Status::iterator, bool > StatusPair;

class WcViewModel : public QObject, public StatusResult, public TargetId
{
  typedef QObject super;
  Q_OBJECT

public:
  WcViewModel( Bookmark* bm, ScModel* model );
  ~WcViewModel();

  // QObject
  bool event( QEvent* e );

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

  // Commands
  void reload();

  void status();
  void statusRefresh( const sc::String& path );
  void statusRefresh( const svn::Paths& paths );
  void status( const sc::String& path, bool refresh );
  void statusResult( StatusParam*, const sc::Error* );
  void diffBase();
  void diffBase( const sc::String& path, bool dir );
  void diffBaseResult( DiffParam*, const sc::Error* );
  void add();
  void remove();
  void revert();
  void commit( bool bookmark = false );
  void editConflict();
  void resolved();
  void log( bool bookmark = false );
  void logGraph();
  void ignore();
  void blame();
  void lock();
  void unlock();
  void cleanup();
  void mkdir();
  void exportx();
  void update( bool bookmark = false );
  void updateRev( bool bookmark = false );
  void branchTag( bool bookmark = false );
  void proplist();
  void proplistResult( PropListParam*, const sc::Error* );
  void propset();
  void propget();
  
  /** run an external process with given file. */
  void run( const sc::String& file );

  /** add all unversioned childs of the current selection. */
  void addUnvrsnd();
  /** delete all missing childs of the current selection. */
  void remMissing();

  // WcViewModel
  /** get latest status for the given path. */
  void getStatus( const sc::String& path, svn::WcStatuss& statuss );
  /** get latest status for the given path. */
  void getStatus( const sc::String& path, svn::WcStatuss& statuss, bool& deepStatus );

  const sc::String& getRootPath() const;
  const sc::String& getRootUrl() const;
  sc::String getUrlFromPath( const sc::String& path );

  Bookmark* getBookmark();

  const WcSelection& getSelection();

  const Version& getVersion();

public slots:
  void move( const sc::String& to, bool base );
  void copy( const sc::String& to );
  void setSelection( const WcSelection& sel );

signals:
  void error( const sc::Error* );
  void updatedStart( const sc::String& );
  void updatedOld( const sc::String&, const svn::WcStatuss& statuss );
  void updatedNew( const sc::String&, const svn::WcStatuss& statuss, bool deep );
  void updatedVersion( const Version& );
  void updatedDeepStatus( const sc::String&, const DeepStatus& );
  void updatedFinish( const sc::String& );
  void showPatch( const QString& source, const QString& filePatch );
  void editProps( const sc::String& name, bool dir );
  /** signal proplist result */
  void proplist( const sc::String& name, const svn::PropListItems& );

  void confirmRevert( bool& proceed );
  void confirmRemove( bool unversioned, bool& force, bool& proceed );
  void confirmMove( bool& force, bool& proceed );
  void confirmUpdate( UpdateParam*, bool& proceed );
  void confirmExport( ExportParam*, bool& proceed );
  void confirmMkdir( sc::String& dir, bool& proceed );
  void confirmCopy( CopyParam*, Project*, bool& proceed );
  void confirmLock( LockParam*, bool& proceed );
  void confirmUnlock( UnlockParam*, bool& proceed );
  void confirmResolved( bool& proceed );
  void confirmPropSet( PropSetParam*, bool& proceed );
  void confirmPropGet( PropGetParam*, bool& proceed );
  void confirmCommit( CommitParam*, bool& proceed );
  void confirmLog( LogParam*, bool& proceed );

  void commandStarted(Bookmark*);
  void commandFinished(Bookmark*);

public:
  bool getAutoRefresh();
  bool getRecursive();
  bool getUpdate();

private:
  void remove( const svn::Paths& unversioned );
  void updateVersion();
  Version calcVersion( const svn::WcStatuss& statuss );
  void updateDeepStatus( const sc::String& path );
  bool isLeafFolder( const sc::String& path );
  DeepStatus calcFlatStatus( const sc::String& path, const svn::WcStatuss& statuss );
  DeepStatus calcDeepStatus( const sc::String& path, const svn::WcStatuss& statuss );
  /* clear status info of the given path */
  void delStatus( const sc::String& path );
  /* insert status info of the given path */
  const StatusInfo& addStatus( const sc::String& path, const svn::WcStatuss& statuss );
  void updateOld( const sc::String& path );
  void updateNew( const sc::String& path, const svn::WcStatuss& statuss );
  bool isSwitchedInParent( const sc::String& path );

  Bookmark*            _bookmark;
  ScModel*             _model;

  Status               _status;
  Version              _version;

  WcSelection          _selection;
};


#endif // _SC_WCVIEWMODEL_H
