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

// sc
#include "Tokenizer.h"
#include "svn/Diff.h"
#include "util/Char.h"

// apr
#include <apr_pools.h>

// sys
#include <assert.h>


class DiffBaton : public svn::DiffBaton
{
public:
  DiffBaton( Tokenizer** tokenizer, bool ignoreWhitespace, apr_pool_t *pool = 0 )
  : _tokenizer(tokenizer), _ignoreWhitespace(ignoreWhitespace)
  {
    apr_status_t status = apr_pool_create(&_pool,pool);
    assert( status == APR_SUCCESS );
  }

  ~DiffBaton()
  {
    apr_pool_destroy(_pool);
  }

  sc::Error* open( svn::Diff::DataSource source )
  {
    return 0;
  }

  sc::Error* close( svn::Diff::DataSource source )
  {
    return 0;
  }

  char* findNextToken( Tokenizer* input )
  {
    char*  t;
    size_t s;

    bool b = input->nextToken( &t, &s );
    if( ! b )
    {
      return 0;
    }

    char* tok = (char*)apr_palloc( _pool, s+1 );
    memcpy( tok, t, s );
    tok[s] = '\0';

    return tok;
  }

  sc::Error* getNextToken( svn::DiffToken** token, svn::Diff::DataSource source )
  {
    *token = 0;

    switch( source )
    {
    case svn::Diff::srcOriginal:
      {
        *token = (svn::DiffToken*)findNextToken( _tokenizer[svn::Diff::srcOriginal] );
        break;
      }
    case svn::Diff::srcModified:
      {
        *token = (svn::DiffToken*)findNextToken( _tokenizer[svn::Diff::srcModified] );
        break;
      }
    case svn::Diff::srcLatest:
      {
        *token = (svn::DiffToken*)findNextToken( _tokenizer[svn::Diff::srcLatest] );
        break;
      }
    case svn::Diff::srcAncestor:
      {
        *token = (svn::DiffToken*)findNextToken( _tokenizer[svn::Diff::srcAncestor] );
        break;
      }
    default:
      {
        assert(false);
        // TODO return error
        break;
      }
    }
    return 0;
  }

  int compareToken( svn::DiffToken* ltoken, svn::DiffToken* rtoken )
  {
    char* left  = (char*)ltoken;
    char* right = (char*)rtoken;

    while( true )
    {
      char lchar = *left++;
      char rchar = *right++;

      if( lchar != rchar )
      {
        if( _ignoreWhitespace )
        {
          while( sc::Char::isWhitespace(lchar) )
          {
            lchar = *left++;
          }
          while( sc::Char::isWhitespace(rchar) )
          {
            rchar = *right++;
          }
        }

        if( lchar != rchar )
        {
          return lchar-rchar;
        }
      }

      if( lchar == 0 && rchar == 0 )
      {
        return 0;
      }
    }
  }

  void discardToken( svn::DiffToken* token )
  {
  }

  void discardAllToken()
  {
    apr_pool_clear(_pool);
  }

private:
  Tokenizer** _tokenizer;

  apr_pool_t* _pool;

  // options
  bool        _ignoreWhitespace;
};


#endif //  _DIFF_BATON_H
