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

// sc
#include "ListCmd2.h"
#include "ListParam.h"
#include "../ListCache.h"
#include "CmdResultCallback.h"
#include "CmdProgressCallback.h"
#include "svn/Client.h"
#include "svn/DirEntry.h"
#include "svn/ClientContext.h"
#include "svn/CancelBaton.h"
#include "svn/InfoBaton.h"
#include "svn/Info.h"
#include "svn/Revision.h"
#include "util/Error.h"

// sys
#include <queue>


class InfoBaton : public svn::InfoBaton
{
public:
  void info( svn::InfoPtr info )
  {
    _info = info;
  };

  svn::Revnumber getRevnumber() const
  {
    // pre 1.2 server 
    if( ! _info )
      return 0;

    return _info->getRevnumber();
  }

private:
  svn::InfoPtr _info;
};


ListCmd2::ListCmd2( ListParam* param, ListCache* lc, CmdResultCallback* cb )
: ScCmd(param->getId()), _param(param), _lc(lc), _cb(cb)
{
}

ListCmd2::~ListCmd2()
{
  delete _cb;
}

typedef std::queue<sc::String> ListUrls;

void ListCmd2::run()
{
  sc::Error* err = sc::Success;

  _prgscb->started( _param, getCancel() );

  ListUrls urls;
  urls.push( _param->getPathOrUrl() );

  while( ! urls.empty() && ! _client->getContext()->getCancelBaton()->isCanceled() )
  {
    svn::DirEntries& entries = _param->getEntries();
    InfoBaton        baton;
    svn::Revnumber   revnum;
    svn::Revision    peg = svn::RevUnspecified;
    if( _param->getRevision()->equals(&svn::RevUnspecified) )
    {
      peg = svn::RevHead;
    }

    err = _client->info( urls.front(), *_param->getRevision(), peg, &baton, false );

    if( err != sc::Success )
    {
      break;
    }

    revnum = baton.getRevnumber();

    // if refresh or not cached..
    if( _param->getRefresh() || (! _lc->getRpList( urls.front(), revnum, entries )) )
    {
      err = _client->ls( urls.front(), *_param->getRevision(), false, entries );

      if( err != sc::Success )
      {
        break;
      }

      _param->setRevnumber(revnum);
      _lc->setRpList( urls.front(), revnum, entries );
    }

    // todo handle recursive case, see StatusCmd2

    urls.pop();
  }

  _param->setError( err );
  _prgscb->finished( _param );

  _cb->handleResult( _param, err );
}
