/* ====================================================================
 * 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_DIFF_H
#define _SVN_DIFF_H

// svn
#include "svn.h"
struct apr_pool_t;
struct svn_diff_t;

// sc
namespace sc {
  class Error;
};

namespace svn
{
class DiffData;
class DiffBaton;
class OutputBaton;

///////////////////////////////////////////////////////////////////////////////
//

class Diff
{
public:
  enum DataSource
  {
    srcOriginal = 0,
    srcModified = 1,
    srcLatest   = 2,
    srcAncestor = 3,

    srcMax      = 4
  };

  Diff( apr_pool_t* pool = 0 );
  virtual ~Diff();

  sc::Error* diff( DiffData** diff, DiffBaton* baton );
  sc::Error* diff3( DiffData** diff, DiffBaton* baton );
  sc::Error* diff4( DiffData** diff, DiffBaton* baton );

private:
  apr_pool_t* _pool;
};


class DiffToken; // just an alias for void


// void *diff_baton, svn_diff_fns_t
class DiffBaton
{
public:
  virtual ~DiffBaton(){}

  virtual sc::Error* open( Diff::DataSource ) = 0;
  virtual sc::Error* close( Diff::DataSource ) = 0;
  virtual sc::Error* getNextToken( DiffToken**, Diff::DataSource ) = 0;
  virtual int    compareToken( DiffToken*, DiffToken* ) = 0;
  virtual void   discardToken( DiffToken* ) = 0;
  virtual void   discardAllToken() = 0;
};

//
///////////////////////////////////////////////////////////////////////////////
//

// svn_diff_t
class DiffData
{
public:
  DiffData(svn_diff_t*);
  virtual ~DiffData();

  sc::Error* output( OutputBaton* );

  bool hasConflicts() const;
  bool hasDifferences() const;

private:
  svn_diff_t* _diff;
};


class DiffOffsets
{
public:
  DiffOffsets();
  DiffOffsets(
    Offset oS, Offset oL,
    Offset mS, Offset mL,
    Offset lS, Offset lL );

  Offset _originalStart;
  Offset _originalLength;
  Offset _modifiedStart;
  Offset _modifiedLength;
  Offset _latestStart;
  Offset _latestLength;
};


// void *output_baton, svn_diff_output_fns_t
class OutputBaton
{
public:
  virtual ~OutputBaton(){}

  virtual sc::Error* common      ( const DiffOffsets& ) = 0;
  virtual sc::Error* diffModified( const DiffOffsets& ) = 0;
  virtual sc::Error* diffLatest  ( const DiffOffsets& ) = 0;
  virtual sc::Error* diffCommon  ( const DiffOffsets& ) = 0;
  virtual sc::Error* conflict    ( const DiffOffsets&, DiffData* ) = 0;
};

//
///////////////////////////////////////////////////////////////////////////////

} // namespace

#endif // _SVN_DIFF_H
