#include "dictionarybar.hh"
#include <QAction>
#include <QApplication>
#include <QMenu>
#include <QContextMenuEvent>
#include "dprintf.hh"

using std::vector;

DictionaryBar::DictionaryBar( QWidget * parent,
                              Config::MutedDictionaries & mutedDictionaries_,
                              Config::Events & events ):
  QToolBar( tr( "Dictionary Bar" ), parent ),
  mutedDictionaries( mutedDictionaries_ ),
  configEvents( events )
{
  setObjectName( "dictionaryBar" );

  connect( &events, SIGNAL( mutedDictionariesChanged() ),
           this, SLOT( mutedDictionariesChanged() ) );

  connect( this, SIGNAL(actionTriggered(QAction*)),
           this, SLOT(actionWasTriggered(QAction*)) );
}

static QString elideDictName( QString const & name )
{
  // Some names are way too long -- we insert an ellipsis in the middle of those

  int const maxSize = 33;

  if ( name.size() <= maxSize )
    return name;

  int const pieceSize = maxSize / 2 - 1;

  return name.left( pieceSize ) + QChar( 0x2026 ) + name.right( pieceSize );
}

void DictionaryBar::setDictionaries( vector< sptr< Dictionary::Class > >
                                     const & dictionaries )
{
  setUpdatesEnabled( false );

  clear();
  dictActions.clear();

  bool use14x21 = false;

  for( unsigned x = 0; x < dictionaries.size(); ++x )
  {
    QIcon icon = dictionaries[ x ]->getNativeIcon();

    QString dictName = QString::fromUtf8( dictionaries[ x ]->
                                            getName().c_str() );

    QAction * action = addAction( icon, elideDictName( dictName ) );

    action->setToolTip( dictName ); // Tooltip need not be shortened

    QString id = QString::fromStdString( dictionaries[ x ]->getId() );

    action->setData( id );

    action->setCheckable( true );

    action->setChecked( !mutedDictionaries.contains( id ) );

    QList< QSize > sizes = icon.availableSizes();

    for( QList< QSize >::iterator i = sizes.begin(); i != sizes.end();
         ++i )
      if ( i->width() == 14 && i->height() == 21 )
        use14x21 = true;

    dictActions.append( action );
  }

  setIconSize( use14x21 ? QSize( 14, 21 ) : QSize( 21, 21 ) );

  setUpdatesEnabled( true );
}


void DictionaryBar::contextMenuEvent( QContextMenuEvent * event )
{
  QMenu menu( this );

  for( QList< QAction * >::iterator i = dictActions.begin();
       i != dictActions.end(); ++i )
  {
    // We need new action, since the one we have has text elided
    QAction * action = menu.addAction( (*i)->icon(), (*i)->toolTip() );

    action->setCheckable( true );
    action->setChecked( (*i)->isChecked() );
    action->setData( QVariant::fromValue( (void *)*i ) );
    // Force "icon in menu" on all platforms, for
    // usability reasons.
    action->setIconVisibleInMenu( true );
  }

  if ( !menu.isEmpty() )
    menu.addSeparator();

  QAction * editAction =
      menu.addAction( QIcon( ":/icons/bookcase.png" ), tr( "Edit this group" ) );

  QAction * result = menu.exec( event->globalPos() );

  if ( result == editAction )
    emit editGroupRequested();
  else
  if ( result && result->data().value< void * >() )
    ( ( QAction * )( result->data().value< void * >() ) )->trigger();

  event->accept();
}

void DictionaryBar::mutedDictionariesChanged()
{
  //DPRINTF( "Muted dictionaries changed\n" );

  // Update actions

  setUpdatesEnabled( false );

  for( QList< QAction * >::iterator i = dictActions.begin();
       i != dictActions.end(); ++i )
  {
    bool isUnmuted = !mutedDictionaries.contains( (*i)->data().toString() );

    if ( isUnmuted != (*i)->isChecked() )
      (*i)->setChecked( isUnmuted );
  }

  setUpdatesEnabled( true );
}

void DictionaryBar::actionWasTriggered( QAction * action )
{
  QString id = action->data().toString();

  if ( id.isEmpty() )
    return; // Some weird action, not our button

  if ( QApplication::keyboardModifiers() &
         ( Qt::ControlModifier | Qt::ShiftModifier ) )
  {
    // Solo mode -- either use the dictionary exclusively, or toggle
    // back all dictionaries if we do that already.

    // Are we solo already?

    bool isSolo = true;

    // For solo, all dictionaries must be unchecked, since we're handling
    // the result of the dictionary being (un)checked, and in case we were
    // in solo, now we would end up with no dictionaries being checked at all.
    for( QList< QAction * >::iterator i = dictActions.begin();
         i != dictActions.end(); ++i )
    {
      if ( (*i)->isChecked() )
      {
        isSolo = false;
        break;
      }
    }

    if ( isSolo )
    {
      // Toggle back all the dictionaries
      for( QList< QAction * >::iterator i = dictActions.begin();
           i != dictActions.end(); ++i )
        mutedDictionaries.remove( (*i)->data().toString() );
    }
    else
    {
      // Make dictionary solo
      for( QList< QAction * >::iterator i = dictActions.begin();
           i != dictActions.end(); ++i )
      {
        QString dictId = (*i)->data().toString();

        if ( dictId == id )
          mutedDictionaries.remove( dictId );
        else
          mutedDictionaries.insert( dictId );
      }
    }
    configEvents.signalMutedDictionariesChanged();
  }
  else
  {
    // Normal mode

    if ( action->isChecked() )
    {
      // Unmute the dictionary

      if ( mutedDictionaries.contains( id ) )
      {
        mutedDictionaries.remove( id );
        configEvents.signalMutedDictionariesChanged();
      }
    }
    else
    {
      // Mute the dictionary

      if ( !mutedDictionaries.contains( id ) )
      {
        mutedDictionaries.insert( id );
        configEvents.signalMutedDictionariesChanged();
      }
    }
  }
}

