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

// sc
#include "svn.h"
#include "ClientTypes.h"
#include "DirEntryTypes.h"
#include "WcStatusTypes.h"
#include "PropListItemTypes.h"
#include "PropGetItemTypes.h"
#include "util/String.h"
namespace sc {
  class Error;
}

// apr
struct apr_pool_t;


namespace svn
{
class ClientContext;
class CommitInfo;
class BlameBaton;
class StatusBaton;
class DiffSummarizeBaton;
class LogBaton;
class Revision;
class InfoBaton;
class CommitBaton;

/**
 * \brief the subversion client interface.
 */
class Client
{
public:
  Client( ClientContext* context, apr_pool_t* pool = 0 );
  virtual ~Client();

  /** svn_client_checkout */
  sc::Error* checkout( Revnumber* resultRev, const sc::String& url, const sc::String& path,
    const Revision& peg, const Revision& rev, bool recurse );

  /** svn_client_update */
  sc::Error* update( Revnumber* resultRev, const sc::String& path, const Revision& rev, bool recurse );

  /** svn_client_switch, because switch is a c++ key word we call it swichx. */
  sc::Error* switchx( Revnumber* resultRev, const sc::String& path, const sc::String& url,
    const Revision& rev, bool recurse );

  /** svn_client_commit2 */
  sc::Error* commit( CommitInfo& resultInfo, const Paths& paths, bool recurse, bool keepLocks );

  /** svn_client_status */
  sc::Error* status( Revnumber* resultRev, const sc::String& path, const Revision& rev,
    StatusBaton *baton, bool recurse, bool all, bool update, bool ignore );

  /** svn_client_ls */
  sc::Error* ls( const sc::String& pathOrUrl, const Revision& rev, bool recurse, DirEntries& entries );

  /** svn_client_mkdir */
  sc::Error* mkdir( CommitInfo& resultInfo, const Paths& pathsOrUrls );

  /** (based on) svn_client_add2 */
  sc::Error* add( const Paths& paths, bool recurse, bool force );

  /** svn_client_delete, because delete is a c++ key word we call it deletex. */
  sc::Error* deletex( CommitInfo& resultInfo, const Paths& pathsOrUrls, bool force );

  /** svn_client_revert */
  sc::Error* revert( const Paths& paths, bool recurse );

  /** svn_client_import */
  sc::Error* import( CommitInfo& resultInfo, const sc::String& path, const sc::String& url,
    bool recurse );

  /** svn_client_blame */
  sc::Error* blame( const sc::String& pathOrUrl, const Revision& begin, const Revision& end,
    BlameBaton* baton );

  /** svn_client_cleanup */
  sc::Error* cleanup( const sc::String& path );

  /** svn_client_relocate */
  sc::Error* relocate( const sc::String& path, const sc::String& fromUrl, const sc::String& toUrl,
    bool recurse );

  /** svn_client_resolved */
  sc::Error* resolved( const sc::String& path, bool recurse );

  /** svn_client_log2 */
  sc::Error* log( const Paths& pathsOrUrls, const Revision& start, const Revision& stop,
    int limit, bool discoverChangedPaths, bool strictNodeHistory, LogBaton* baton );

  /** svn_client_diff */
  sc::Error* diff( const sc::String& pathOrUrl1, const Revision& rev1,
    const sc::String& pathOrUrl2, const Revision& rev2, bool recurse, bool ancestry,
    bool deleted, bool patch, sc::String& patchFile );

  /** svn_client_diff_peg */
  sc::Error* diff( const sc::String& srcPathOrUrl, const Revision& rev1,
    const Revision& rev2, const Revision& peg, bool recurse, bool ancestry, bool deleted,
    bool patch, sc::String& patchFile );

  /** svn_client_merge */
  sc::Error* merge( const sc::String& pathOrUrl1, const Revision& rev1, const sc::String& pathOrUrl2,
    const Revision& rev2, const sc::String& targetPath, bool recurse, bool ancestry, bool force,
    bool dryRun );

  /** svn_client_merge_peg */
  sc::Error* merge( const sc::String& srcPathOrUrl, const Revision& rev1, const Revision& rev2,
    const Revision& peg, const sc::String& targetPath, bool recurse, bool ancestry, bool force,
    bool dryRun );

  /** svn_client_diff_summarize */
  sc::Error* diffSummarize( const sc::String& pathOrUrl1, const Revision& rev1,
    const sc::String& pathOrUrl2, const Revision& rev2, DiffSummarizeBaton* baton, bool recurse,
    bool ancestry );

  /** svn_client_diff_summarize */
  sc::Error* diffSummarize( const sc::String& srcPathOrUrl, const Revision& rev1,
    const Revision& rev2, const Revision& peg, DiffSummarizeBaton* baton, bool recurse,
    bool ancestry );

  sc::Error* visualDiff( const sc::String& pathOrUrl1, const Revision& rev1,
    const sc::String& pathOrUrl2, const Revision& rev2 );

  sc::Error* visualDiff( const sc::String& srcPathOrUrl, const Revision& rev1,
    const Revision& rev2, const Revision& peg );

  sc::Error* visualMerge( const WcStatusPtr file );

  /** svn_client_copy */
  // multiple files will only work as a working copy operation.
  // pass only a single file in a repository operation.
  sc::Error* copy( CommitInfo& resultInfo, const Paths& srcPathsOrUrls, const Revision& srcRev,
    const sc::String& dstPathOrUrl );

  /** svn_client_move2 */
  // multiple files will only work as a working copy operation.
  // pass only a single file in a repository operation.
  sc::Error* move( CommitInfo& resultInfo, const Paths& srcPathsOrUrls, const Paths& dstPathsOrUrls,
    bool force );

  /** svn_client_export2, because gcc icomplains about export we call it exportx */
  sc::Error* exportx( Revnumber* resultRev, const sc::String& srcPathOrUrl, const Revision& srcRev,
    const sc::String& dstPath, bool force, const sc::String& eol );

  /** svn_client_cat2 */
  sc::Error* cat( sc::String& out, const sc::String& pathOrUrl, const Revision& rev,
    const Revision& peg );

  /** svn_client_proplist */
  sc::Error* proplist( PropListItems& items, const sc::String& pathOrUrl, const Revision& rev,
    bool recurse );

  /** svn_client_propget */
  sc::Error* propget( PropGetItems& items, const sc::String& propName, const sc::String& pathOrUrl,
    const Revision& rev, bool recurse );

  /** svn_client_propset */
  sc::Error* propset( const sc::String& propName, const sc::String& propVal, const sc::String&
    path, bool recurse );

  /** svn_client_revprop_set */
  sc::Error* propsetrev(const sc::String& propName, const sc::String& propVal, const sc::String&
    pathOrUrl, const Revision& srcRev, Revnumber* resultRev, bool force );

  /** svn_client_lock */
  sc::Error* lock( const Paths& pathsOrUrls, const sc::String& comment, bool stealLocks );

  /** svn_client_unlock */
  sc::Error* unlock( const Paths& pathsOrUrls, bool breakLocks );

  /** svn_client_info */
  sc::Error* info( const sc::String& pathOrUrl, const Revision& rev, const Revision& peg,
    InfoBaton* baton, bool recurse );

  /** ra_lib->get_latest_revnum, ra_lib->get_repos_root */
  sc::Error* details( Revnumber* resultRev, sc::String& root, const sc::String& pathOrUrl );

  const ClientContext* getContext() const;
  void setCommitBaton( CommitBaton* baton );


public:
  static bool isWorkingCopy( const sc::String& path );
  static bool getUrlFromPath( const sc::String& pathOrUrl, sc::String& );

private:
#if 0
  // ra_lib->get_latest_revnum
  Error* getHeadRevision( Revnumber* resultRev, const sc::String& pathOrUrl );

  // ra_lib->get_repos_root
  Error* getReposRoot( const sc::String& pathOrUrl, sc::String& root );
#endif

private:
  static const char* preparePathOrUrl( const char* pathOrUrl, apr_pool_t* pool );


  apr_pool_t*    _pool;
  ClientContext* _context;
};


} // namespace


#endif // _SVN_CLIENT_H
