/* ====================================================================
 * Copyright (c) 2006-2007, 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 "config.h"
#include "LogGraphCanvasView.h"
#include "LogGraphCanvasItems.h"
#include "sublib/ActionStorage.h"
#include "sublib/IconFactory.h"

// qt
#include <QtGui/QMouseEvent>
#include <QtGui/QToolTip>
#include <QtGui/QAction>
#include <QtGui/QMenu>
#include <Qt3Support/Q3CanvasView>


enum ActionsLogGraph
{
  ActionLogGraphDiff
};


LogGraphCanvasView::LogGraphCanvasView( QWidget* parent )
: super(parent), _shiftDown(false), _sel1(NULL), _sel2(NULL)
{
  setFocusPolicy(Qt::WheelFocus);
  setMouseTracking(true);
  viewport()->setMouseTracking(true);

  // setup actions, @todo move to LogGraphDialog for toolbar stuff
  _actions = new ActionStorage();
  QAction* action;

  action = new QAction( _q("&diff.."), this );
  action->setShortcut(  _q("Ctrl+Shift+D") );
  action->setStatusTip( _q("show diff between 2 selected revisions") );
  action->setIcon( IconFactory::createIcon("Diff-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionLogGraphDiff, action );
  connect( action, SIGNAL(triggered()), this, SLOT(diffTrigger()) );

  // setup menu
  _popup = new QMenu(this);
  action->addTo(_popup);
}

LogGraphCanvasView::~LogGraphCanvasView()
{
  delete _popup;
  delete _actions;
}

bool LogGraphCanvasView::event( QEvent* e )
{
  if( e->type() == QEvent::ToolTip )
  {
    QHelpEvent* he  = static_cast<QHelpEvent*>(e);
    QString     tip = getTooltip( he->pos() );

    if( ! tip.isEmpty() )
    {
      QToolTip::showText( he->globalPos(), tip );
    }
    else
    {
      QToolTip::hideText();
    }
  }
  return super::event(e);
}

void LogGraphCanvasView::mousePressEvent( QMouseEvent* e )
{
  if( e->button() == Qt::RightButton )
  {
    return;
  }

  // clear old selection
  if( ! _shiftDown )
  {
    clearSelection();
  }

  QPoint pos = viewportToContents(e->pos());
  QPoint wmp = worldMatrix().invert().map(pos);

  Q3CanvasItemList list = canvas()->collisions(wmp);
  if( list.size() > 0 )
  {
    addSelection( dynamic_cast<LogGraphCanvasItem*>(list.first()) );
  }
  canvas()->update();
}

void LogGraphCanvasView::mouseMoveEvent( QMouseEvent* e )
{
#if 0
  static QWidget*       logtip = NULL;
  static QPoint         logpos;

  QPoint pos = viewportToContents(e->pos());
  QPoint wmp = worldMatrix().invert().map(pos);

  QCanvasItemList list = canvas()->collisions(wmp);

  for( QCanvasItemList::Iterator it = list.begin(); it != list.end(); it++ )
  {
    CanvasRev* rev = dynamic_cast<CanvasRev*>(*it);
  }
#endif
}

void LogGraphCanvasView::contextMenuEvent( QContextMenuEvent* e )
{
  _popup->exec(e->globalPos());
}

void LogGraphCanvasView::keyPressEvent( QKeyEvent* e )
{
  if( e->key() == Qt::Key_Shift )
  {
    _shiftDown = true;
  }
  else
  {
    super::keyPressEvent(e);
  }
}

void LogGraphCanvasView::keyReleaseEvent( QKeyEvent* e )
{
  if( e->key() == Qt::Key_Shift )
  {
    _shiftDown = false;
  }
  else
  {
    super::keyPressEvent(e);
  }
}

void LogGraphCanvasView::diffTrigger()
{
  emit diffRequested();
}

void LogGraphCanvasView::addSelection( LogGraphCanvasItem* item )
{
  if( _sel1 == NULL )
  {
    _sel1 = item;
    _sel1->setSelected(true);
    canvas()->setChanged(_sel1->boundingRect());
    return;
  }
  else if( _sel1 == item )
  {
    return;
  }

  // if we already have a second selection, clear the first
  // and change second to first.
  if( _sel2 != NULL && _sel2 != item )
  {
    _sel1->setSelected(false);
    canvas()->setChanged(_sel1->boundingRect());

    _sel1 = _sel2;
    _sel2 = NULL;
  }

  if( _sel2 == NULL )
  {
    _sel2 = item;
    _sel2->setSelected(true);
    canvas()->setChanged(_sel2->boundingRect());
  }

  _actions->enableAction( ActionLogGraphDiff, _sel1 && _sel2 );
  emit selectionChanged( _sel1 && _sel2 );
}

void LogGraphCanvasView::clearSelection()
{
  if( _sel1 != NULL )
  {
    _sel1->setSelected(false);
    canvas()->setChanged(_sel1->boundingRect());
    _sel1 = NULL;
  }

  if( _sel2 != NULL )
  {
    _sel2->setSelected(false);
    canvas()->setChanged(_sel2->boundingRect());
    _sel2 = NULL;
  }

  _actions->enableAction( ActionLogGraphDiff, false );
  emit selectionChanged( false );
}

const LogGraphCanvasItem* LogGraphCanvasView::getSelection1() const
{
  return _sel1;
}

const LogGraphCanvasItem* LogGraphCanvasView::getSelection2() const
{
  return _sel2;
}

const QString& LogGraphCanvasView::getRoot() const
{
  return _root;
}

void LogGraphCanvasView::setRoot( QString& root )
{
  _root = root;
}

QString LogGraphCanvasView::getTooltip( const QPoint &pos )
{
  QPoint cpos = viewportToContents(pos);
  QPoint cwmp = worldMatrix().invert().map(cpos);
  Q3CanvasItemList list = canvas()->collisions(cwmp);

  if( list.size() > 0 )
  {
    LogGraphCanvasItem* item = dynamic_cast<LogGraphCanvasItem*>(list.first());
    if( item )
    {
      return item->getTooltip();
    }
  }

  return QString::null;
}


#if 0
class CanvasToolTip //: public QToolTip
{
public:
  CanvasToolTip( QWidget* parent ) //: QToolTip( parent )
  {
  }

  virtual ~CanvasToolTip()
  {
  }

  void maybeTip( const QPoint &pos );
};

void CanvasToolTip::maybeTip( const QPoint &pos )
{
  LogGraphCanvasView* cv = (LogGraphCanvasView*)parentWidget();

  QPoint cpos = cv->viewportToContents(pos);
  QPoint cwmp = cv->worldMatrix().invert().map(cpos);

  Q3CanvasItemList list = cv->canvas()->collisions(cwmp);
  if( list.size() > 0 )
  {
    LogGraphCanvasPath* path = dynamic_cast<LogGraphCanvasPath*>(list.first());
    if( path )
    {
      QPoint p( path->rect().x(), path->rect().y() );
      QRect  pr( path->rect() );
      pr.setHeight( 20 /*PathBoxTextHeigh*/ );

      QPoint w =  cv->worldMatrix().map(p);
      QRect  wr = cv->worldMatrix().mapRect(pr);
      QPoint r = cv->contentsToViewport(w);
      QSize  s = QSize( wr.width(), wr.height() );

      //tip( QRect(r,s), path->getFullName() );
    }

    LogGraphCanvasRev* rev = dynamic_cast<LogGraphCanvasRev*>(list.first());
    if( rev )
    {
      QPoint p( rev->rect().x(), rev->rect().y() );

      QPoint w  = cv->worldMatrix().map(p);
      QRect  wr = cv->worldMatrix().mapRect(rev->rect());
      QPoint r  = cv->contentsToViewport(w);
      QSize  s  = QSize( wr.width(), wr.height() );


      QString text = QString(
        "<qt><table cellpadding=0 cellspacing=0>"
        "<tr><td><nobr>%1</nobr></td></tr>")
        .arg(QString::fromUtf8(rev->getNode()->getName()));

      QDateTime date;
      date.setTime_t( (uint)apr_time_sec(rev->getNode()->getLog()->getDate()) );
      QString qdate = date.toString( getDateFormat() );

      text += QString(
        "<tr><td><nobr>r%1, %2, %3</nobr></td></tr>" )
        .arg(rev->getNode()->getLog()->getRevnumber())
        .arg(qdate)
        .arg(QString::fromUtf8(rev->getNode()->getLog()->getAuthor()));

      QString msg = QString::fromUtf8(rev->getNode()->getLog()->getMessage());
      QString cut = msg.section( '\n', 0, 14,
        QString::SectionIncludeLeadingSep | QString::SectionIncludeTrailingSep );
      QString cutmsg;
      if( cut.length() < msg.length() )
      {
        cutmsg = QString("<tr><td>%2<td></tr>").arg( _q(".... (cut)") );
      }

      text += QString(
        "<tr><td>&nbsp;</td></tr>"
        "<tr><td><pre>%1</pre></td></tr>"
        "%2"
        "</table></qt>")
        .arg(cut)
        .arg(cutmsg);

      //tip( QRect(r,s), text );
    }
  }
}
#endif
