/* ====================================================================
 * Copyright 2008-2009  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 "WcViewLogWidget.h"
#include "Cancel.h"
#include "events/CustomEvents.h"
#include "events/LoggingEvent.h"
#include "sublib/Utility.h"
#include "sublib/IconFactory.h"

// qt
#include <QtCore/QEvent>
#include <QtGui/QHeaderView>
#include <QtGui/QMouseEvent>
#include <QtGui/QToolButton>
#include <QtGui/QItemDelegate>

// sys
#include <cstdio>


enum LogColumns 
{
  ColAction  = 0,
  ColMessage = 1,
  ColButton  = 2,
  ColData    = 3
};

enum Data
{
  CallbackRole   = Qt::UserRole,
  ActiveRole     = Qt::UserRole+1,
  CancelableRole = Qt::UserRole+2,
  IdRole         = Qt::UserRole+3,
  MsgRole        = Qt::UserRole+4
};

Q_DECLARE_METATYPE(Cancel*)


class Delegate : public QItemDelegate
{
  typedef QItemDelegate super;

public:
  Delegate( QObject* parent ) : QItemDelegate(parent)
  {
  }

  void paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const 
  {
    if( index.column() == ColButton )
      return;

    super::paint(painter,option,index);
  }
};

WcViewLogWidget::WcViewLogWidget( QWidget* parent )
: super(parent)
{
  _cancel = new QIcon(IconFactory::createIcon("Cancel-Normal.png"));

#if QT_VERSION > 0x040400
  setHeaderHidden(true);
#else
  header()->setHidden(true);
#endif // QT_VERSION

  setColumnCount(4);
  hideColumn(ColData);

  header()->moveSection(ColButton,ColAction);
  header()->setResizeMode(ColButton,QHeaderView::Fixed);
  header()->resizeSection( ColButton, 20 );
  header()->setResizeMode(ColAction,QHeaderView::ResizeToContents);
  header()->setResizeMode(ColMessage,QHeaderView::ResizeToContents);
  header()->setStretchLastSection(true);
  setAllColumnsShowFocus(true);
  setTextElideMode(Qt::ElideNone);

  connect( 
    this, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),
    this, SLOT(itemDoubleClick(QTreeWidgetItem*,int)) );

  setItemDelegate( new Delegate(this) );
}

WcViewLogWidget::~WcViewLogWidget()
{
  delete _cancel;
}

void WcViewLogWidget::itemDoubleClick( QTreeWidgetItem* item, int column )
{
  if( column == 0 )
    return;

  if( item->isExpanded() )
    collapseItem(item);
  else
    expandItem(item);
}

void WcViewLogWidget::customEvent( QEvent* ce )
{
  switch( ce->type() )
  {
  case ScLoggingEvent:
    {
      LoggingEvent*  le = (LoggingEvent*)ce;
      LogDataPtr     ld = le->getData();

      // command start/stop
      if( ld->isStarted() )
      {
        QTreeWidgetItem* item = new QTreeWidgetItem(this);

        item->setData( ColData, IdRole, (uint)ld->getId() );
        item->setData( ColData, ActiveRole, true );
        item->setData( ColData, MsgRole, QString::fromUtf8(ld->getMsg()) );
        item->setText( ColAction, QString::fromUtf8(ld->getAction()) );
        scrollToItem(item);

        if( ld->isCancelable() )
        {
          item->setData( ColData, CancelableRole, true );
          item->setData( ColData, CallbackRole, QVariant::fromValue(ld->getCancel()) );
          item->setText( ColMessage, item->data(ColData,MsgRole).toString()+"\n..." );
          //item->setFlags(Qt::ItemIsEnabled);

          QToolButton* cb = new QToolButton(this);
          cb->setStyleSheet("QToolButton {border: 0px none; icon-size: 22px;}");
          cb->setAutoRaise(true);
          cb->setIcon(*_cancel);
          connect( cb, SIGNAL(clicked()), this, SLOT(canceled()) );
          setItemWidget(item,ColButton,cb);
        }
        else
        {
          item->setData( ColData, CancelableRole, false );
          item->setText( ColMessage, item->data(ColData,MsgRole).toString() );
        }
      }
      else if( ld->isError() )
      {
        QPixmap err(getIconDir() + "FailedSmall.png");
        QTreeWidgetItem* parent = findItem(ld->getId());
        parent->setIcon( ColAction, err );
        
        QTreeWidgetItem* item = new QTreeWidgetItem(parent);
        item->setText( ColAction, QString::fromUtf8(ld->getAction()) + ":" );
        item->setText( ColMessage, QString::fromUtf8(ld->getMsg()) );        
        item->setIcon( ColAction, err );
      }
      else if( ld->isFinished() )
      {
        QTreeWidgetItem* parent = findItem(ld->getId());
        setItemWidget(parent,ColButton,NULL);        
        parent->setData( ColData, ActiveRole, false );
        parent->setText( ColMessage, parent->data(ColData,MsgRole).toString()+
          " - " + QString::fromUtf8(ld->getMsg()) + "." );

        QTreeWidgetItem* item = new QTreeWidgetItem(parent);
        item->setText( ColAction, QString::fromUtf8(ld->getAction()) + ":" );
        item->setText( ColMessage, QString::fromUtf8(ld->getMsg()) );
      }
      // command progress
      else if( ld->isRunning() )
      {
        QTreeWidgetItem* parent = findItem(ld->getId());
        parent->setText( ColMessage, parent->data(ColData,MsgRole).toString()+
          "\n" + QString::fromUtf8(ld->getAction()) +
          " " + QString::fromUtf8(ld->getMsg()) + "." );

        QTreeWidgetItem* item = new QTreeWidgetItem(parent);
        item->setText( ColAction,  QString::fromUtf8(ld->getAction()) + ":" );
        item->setText( ColMessage, QString::fromUtf8(ld->getMsg()) );
      }
      ce->accept();
      break;
    }
  default:
    {
      printf( "WcViewLogWidget: unknown custom event %d!\n", ce->type() );
    }
  }

  // settings the resize mode doesn't seem to work.
  resizeColumnToContents(ColAction);
  //resizeColumnToContents(ColButton);
  resizeColumnToContents(ColMessage);
}

void WcViewLogWidget::canceled()
{
  QTreeWidgetItem* item = findItem();
  if(!item)
    return;

  disable(item);
  cancel(item);
}

QTreeWidgetItem* WcViewLogWidget::findItem()
{
  QToolButton* b = dynamic_cast<QToolButton*>(sender());
  for( int idx = 0; idx < topLevelItemCount(); idx++ )
  {
    QTreeWidgetItem* item = topLevelItem(idx);
    if( b == itemWidget(item,ColButton) )
    {
      return item;
    }
  }
  return NULL;
}

QTreeWidgetItem* WcViewLogWidget::findItem( uint id )
{
  for( int idx = 0; idx < topLevelItemCount(); idx++ )
  {
    QTreeWidgetItem* item = topLevelItem(idx);
    if( id == item->data(ColData,IdRole).toUInt() )
    {
      return item;
    }
  }
  return NULL;
}

void WcViewLogWidget::disable(QTreeWidgetItem* item)
{
  itemWidget(item,ColButton)->setDisabled(true);
}

void WcViewLogWidget::cancel(QTreeWidgetItem* item)
{
  Cancel* cb = item->data(ColData,CallbackRole).value<Cancel*>();
  if(!cb)
    return;

  cb->setCanceled();
}
