/* ====================================================================
 * Copyright (c) 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 "MergeViewModel.h"
#include "ScModel.h"
#include "PostCmdResult.h"
#include "commands/MergeParam.h"
#include "commands/MergeCmd.h"
#include "events/ScParamEvent.h"
#include "events/EventSupport.h"
#include "sublib/TargetRepository.h"
#include "svn/Path.h"


class MergeViewModelParamVisitor :
  public ParamVisitor<MergeParam>
{
public:
  MergeViewModelParamVisitor( MergeViewModel* model )
    : _model(model)
  {
  }

  void run( ScParamEvent* e )
  {
    _event = e;
    _event->getParam()->accept(this);
  }

  void visit( MergeParam* p )
  {
    _model->mergeResult( p, _event->getError() );
  }

private:
  ScParamEvent*   _event;
  MergeViewModel* _model;
};

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


MergeViewModel::MergeViewModel( bool changePathOrUrl1, bool changePathOrUrl2,
  bool changeType, bool pegMerge, ScModel* model )
  : TargetId(this), _model(model), _changePathOrUrl1(changePathOrUrl1),
  _changePathOrUrl2(changePathOrUrl2), _changeType(changeType), _pegMerge(pegMerge)
{
  _pathOrUrl1 = "unset";
  _pathOrUrl2 = "unset";
  _rev1       = svn::RevisionPtr(new svn::Revision(svn::Revision_Unspecified));
  _rev2       = svn::RevisionPtr(new svn::Revision(svn::Revision_Unspecified));
  _revPeg     = svn::RevisionPtr(new svn::Revision(svn::Revision_Unspecified));
  _recursive  = _model->getOptionCommandRecurse();
  _copies     = true;
  _force      = false;
}

MergeViewModel::~MergeViewModel()
{
}

bool MergeViewModel::event( QEvent* e )
{
  switch( e->type() )
  {
  case ScParameterEvent:
    {
      MergeViewModelParamVisitor visitor(this);
      visitor.run(dynamic_cast<ScParamEvent*>(e));
      return true;
    }
  default:
    {
      return super::event(e);
    }
  }
}

const sc::String& MergeViewModel::getPathOrUrl1()
{
  return _pathOrUrl1;
}

const sc::String& MergeViewModel::getPathOrUrl2()
{
  return _pathOrUrl2;
}

const svn::RevisionPtr MergeViewModel::getRevisionPeg()
{
  return _revPeg;
}

const svn::RevisionPtr MergeViewModel::getRevision1()
{
  return _rev1;
}

const svn::RevisionPtr MergeViewModel::getRevision2()
{
  return _rev2;
}

bool MergeViewModel::getRecursive()
{
  return _recursive;
}

bool MergeViewModel::getCopies()
{
  return _copies;
}

bool MergeViewModel::getForce()
{
  return _force;
}

const sc::String& MergeViewModel::getDefaultTarget()
{
  return _targetDefault;
}

const sc::String& MergeViewModel::getTarget()
{
  return _target;
}

const svn::Paths& MergeViewModel::getTargets()
{
  return _targets;
}

bool MergeViewModel::getChangePathOrUrl1()
{
  return _changePathOrUrl1;
}

bool MergeViewModel::getChangePathOrUrl2()
{
  return _changePathOrUrl2;
}

bool MergeViewModel::getChangeType()
{
  return _changeType;
}

bool MergeViewModel::getPegMerge()
{
  return _pegMerge;
}

void MergeViewModel::setPathOrUrl1( const sc::String& pathOrUrl )
{
  _pathOrUrl1 = pathOrUrl;
}

void MergeViewModel::setPathOrUrl2( const sc::String& pathOrUrl )
{
  _pathOrUrl2 = pathOrUrl;
}

void MergeViewModel::setRevisionPeg( svn::RevisionPtr rev )
{
  _revPeg = rev;
}

void MergeViewModel::setRevision1( svn::RevisionPtr rev )
{
  _rev1 = rev;
}

void MergeViewModel::setRevision2( svn::RevisionPtr rev )
{
  _rev2 = rev;
}

void MergeViewModel::setRecursive( bool on )
{
  _recursive = on;
}

void MergeViewModel::setCopies( bool on )
{
  _copies = on;
}

void MergeViewModel::setForce( bool on )
{
  _force = on;
}

void MergeViewModel::setPegMerge( bool on )
{
  _pegMerge = on;
}

void MergeViewModel::setDefaultTarget( const sc::String& target )
{
  _targetDefault = target;
}

void MergeViewModel::setTarget( const sc::String& target )
{
  _target = target;
}

void MergeViewModel::addTarget( const sc::String& target )
{
  _targets.push_back(target);
}

void MergeViewModel::merge()
{
  MergeParam* param = new MergeParam(
    _pathOrUrl1, _rev1,
    _pathOrUrl2, _rev2,
    getPegMerge(),
    calcPegRev(),
    _target,
    _recursive,
    _copies,
    false,
    _force,
    false /* dryrun */ );

  MergeCmd* cmd = new MergeCmd( param, new PostCmdResult(this) );
  _model->runThreaded(cmd);
}

void MergeViewModel::dryrun()
{
  MergeParam* param = new MergeParam(
    _pathOrUrl1, _rev1,
    _pathOrUrl2, _rev2,
    getPegMerge(),
    calcPegRev(),
    _target,
    _recursive,
    _copies,
    false,
    _force,
    true /* dryrun */ );

  MergeCmd* cmd = new MergeCmd( param, new PostCmdResult(this) );
  _model->runThreaded(cmd);
}

void MergeViewModel::mergeResult( MergeParam* p, const sc::Error* e )
{
}

svn::RevisionPtr MergeViewModel::calcPegRev()
{
  if( ! getPegMerge() || ! _revPeg->equals( &svn::RevUnspecified )  )
    return _revPeg;

  if( svn::Path::isUrl(_pathOrUrl1) )
  {
    return svn::RevisionHead;
  }
  else
  {
    return svn::RevisionBase;
  }
}
