/*
    This file is part of KAddressBook.
    Copyright (c) 2002 Mike Pilone <mpilone@slac.com>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of TQt, and distribute the resulting executable,
    without including the source code for TQt in the source distribution.
*/

#include <tqheader.h>
#include <tqiconset.h>
#include <tqimage.h>
#include <tqdragobject.h>
#include <tqcombobox.h>
#include <tqpainter.h>
#include <tqbrush.h>
#include <tqevent.h>

#include <tdelocale.h>
#include <tdeglobalsettings.h>
#include <kdebug.h>
#include <tdeconfig.h>
#include <tdeapplication.h>
#include <kurl.h>
#include <tdeabc/addressbook.h>
#include <tdeabc/addressee.h>
#include <tdeimproxy.h>

#include "kaddressbooktableview.h"

#include "contactlistview.h"

/////////////////////////////////
// DynamicTip Methods

DynamicTip::DynamicTip( ContactListView *parent)
  : TQToolTip( parent )
{
}

void DynamicTip::maybeTip( const TQPoint &pos )
{
  if (!parentWidget()->inherits( "ContactListView" ))
    return;

  ContactListView *plv = (ContactListView*)parentWidget();
  if (!plv->tooltips())
    return;

  TQPoint posVp = plv->viewport()->pos();

  TQListViewItem *lvi = plv->itemAt( pos - posVp );
  if (!lvi)
    return;

  ContactListViewItem *plvi = dynamic_cast< ContactListViewItem* >(lvi);
  if (!plvi)
    return;

  TQString s;
  TQRect r = plv->itemRect( lvi );
  r.moveBy( posVp.x(), posVp.y() );

    //kdDebug(5720) << "Tip rec: " << r.x() << "," << r.y() << "," << r.width()
    //          << "," << r.height() << endl;

  TDEABC::Addressee a = plvi->addressee();
  if (a.isEmpty())
    return;

  s += i18n("label: value", "%1: %2").arg(a.formattedNameLabel())
                                     .arg(a.formattedName());

  s += '\n';
  s += i18n("label: value", "%1: %2").arg(a.organizationLabel())
                                       .arg(a.organization());

  TQString notes = a.note().stripWhiteSpace();
  if ( !notes.isEmpty() ) {
    notes += '\n';
    s += '\n' + i18n("label: value", "%1: \n").arg(a.noteLabel());
    TQFontMetrics fm( font() );

    // Begin word wrap code based on TQMultiLineEdit code
    int i = 0;
    bool doBreak = false;
    int linew = 0;
    int lastSpace = -1;
    int a = 0;
    int lastw = 0;

    while ( i < int(notes.length()) ) {
      doBreak = false;
      if ( notes[i] != '\n' )
        linew += fm.width( notes[i] );

      if ( lastSpace >= a && notes[i] != '\n' )
        if  (linew >= parentWidget()->width()) {
          doBreak = true;
          if ( lastSpace > a ) {
            i = lastSpace;
            linew = lastw;
          }
          else
            i = TQMAX( a, i-1 );
        }

      if ( notes[i] == '\n' || doBreak ) {
        s += notes.mid( a, i - a + (doBreak?1:0) ) +"\n";

        a = i + 1;
        lastSpace = a;
        linew = 0;
      }

      if ( notes[i].isSpace() ) {
        lastSpace = i;
        lastw = linew;
      }

      if ( lastSpace <= a ) {
        lastw = linew;
      }

      ++i;
    }
  }

  tip( r, s );
}

///////////////////////////
// ContactListViewItem Methods

ContactListViewItem::ContactListViewItem(const TDEABC::Addressee &a,
                                         ContactListView *parent,
                                         TDEABC::AddressBook *doc,
                                         const TDEABC::Field::List &fields,
                                         KIMProxy *proxy )
  : TDEListViewItem(parent), mAddressee(a), mFields( fields ),
    parentListView( parent ), mDocument(doc), mIMProxy( proxy )
{
  if ( mIMProxy )
    mHasIM = mIMProxy->isPresent( mAddressee.uid() );
  else
    mHasIM = false;
  refresh();
}

TQString ContactListViewItem::key(int column, bool ascending) const
{
  // Preserve behaviour of TQListViewItem::key(), otherwise we cause a crash if the column does not exist
  if ( column >= parentListView->columns() )
    return TQString();

#if TDE_VERSION >= 319
  Q_UNUSED( ascending )
  if ( parentListView->showIM() ) {
    // in this case, one column is reserved for IM presence
    // so we have to process it differently
    if ( column == parentListView->imColumn() ) {
      // increment by one before converting to string so that -1 is not greater than 1
      // create the sort key by taking the numeric status 0 low, 5 high, and subtracting it from 5
      // so that the default ascending gives online before offline, etc.
      TQString key = TQString::number( 5 - ( mIMProxy->presenceNumeric( mAddressee.uid() ) + 1 ) );
      return key;
    }
    else {
      return mFields[ column ]->sortKey( mAddressee );
    }
  }
  else
    return mFields[ column ]->sortKey( mAddressee );
#else
  return TQListViewItem::key( column, ascending ).lower();
#endif
}

void ContactListViewItem::paintCell(TQPainter * p,
                                    const TQColorGroup & cg,
                                    int column,
                                    int width,
                                    int align)
{
  TDEListViewItem::paintCell(p, cg, column, width, align);

  if ( !p )
    return;

  if (parentListView->singleLine()) {
    p->setPen( parentListView->alternateColor() );
    p->drawLine( 0, height() - 1, width, height() - 1 );
  }
}


ContactListView *ContactListViewItem::parent()
{
  return parentListView;
}


void ContactListViewItem::refresh()
{
  // Avoid crash on exit
  if ( !mDocument ) {
      return;
  }

  // Update our addressee, since it may have changed elsewhere
  mAddressee = mDocument->findByUid(mAddressee.uid());
  if (mAddressee.isEmpty())
    return;

  int i = 0;
  // don't show unknown presence, it's not interesting
  if ( mHasIM ) {
    if ( mIMProxy->presenceNumeric( mAddressee.uid() ) > 0 )
      setPixmap( parentListView->imColumn(), mIMProxy->presenceIcon( mAddressee.uid() ) );
    else
      setPixmap( parentListView->imColumn(), TQPixmap() );
  }

  TDEABC::Field::List::ConstIterator it;
  for ( it = mFields.begin(); it != mFields.end(); ++it ) {
    if ( (*it)->label() == TDEABC::Addressee::birthdayLabel() ) {
      TQDate date = mAddressee.birthday().date();
      if ( date.isValid() )
        setText( i++, TDEGlobal::locale()->formatDate( date, true ) );
      else
        setText( i++, "" );
    } else
      setText( i++, (*it)->value( mAddressee ) );
  }
}

void ContactListViewItem::setHasIM( bool hasIM )
{
  mHasIM = hasIM;
}

///////////////////////////////
// ContactListView

ContactListView::ContactListView(KAddressBookTableView *view,
                                 TDEABC::AddressBook* /* doc */,
                                 TQWidget *parent,
                                 const char *name )
  : TDEListView( parent, name ),
    pabWidget( view ),
    oldColumn( 0 )
{
  mABackground = true;
  mSingleLine = false;
  mToolTips = true;
  mShowIM = true;
  mAlternateColor = TDEGlobalSettings::alternateBackgroundColor();

  setAlternateBackgroundEnabled(mABackground);
  setAcceptDrops( true );
  viewport()->setAcceptDrops( true );
  setAllColumnsShowFocus( true );
  setShowSortIndicator(true);
  setSelectionModeExt( TDEListView::Extended );
  setDropVisualizer(false);

  connect(this, TQ_SIGNAL(dropped(TQDropEvent*)),
          this, TQ_SLOT(itemDropped(TQDropEvent*)));

  new DynamicTip( this );
}

void ContactListView::paintEmptyArea( TQPainter * p, const TQRect & rect )
{
  TQBrush b = palette().brush(TQPalette::Active, TQColorGroup::Base);

  // Get the brush, which will have the background pixmap if there is one.
  if (b.pixmap())
  {
    p->drawTiledPixmap( rect.left(), rect.top(), rect.width(), rect.height(),
      *(b.pixmap()),
      rect.left() + contentsX(),
      rect.top() + contentsY() );
  }

  else
  {
    // Do a normal paint
    TDEListView::paintEmptyArea(p, rect);
  }
}

void ContactListView::contentsMousePressEvent(TQMouseEvent* e)
{
  presspos = e->pos();
  TDEListView::contentsMousePressEvent(e);
}


// To initiate a drag operation
void ContactListView::contentsMouseMoveEvent( TQMouseEvent *e )
{
  if ((e->state() & TQt::LeftButton) && (e->pos() - presspos).manhattanLength() > 4 ) {
    emit startAddresseeDrag();
  }
  else
    TDEListView::contentsMouseMoveEvent( e );
}

bool ContactListView::acceptDrag(TQDropEvent *e) const
{
  return TQTextDrag::canDecode(e);
}

void ContactListView::itemDropped(TQDropEvent *e)
{
  contentsDropEvent(e);
}

void ContactListView::contentsDropEvent( TQDropEvent *e )
{
  emit addresseeDropped(e);
}

void ContactListView::setAlternateBackgroundEnabled(bool enabled)
{
  mABackground = enabled;

  if (mABackground)
  {
    setAlternateBackground(mAlternateColor);
  }
  else
  {
    setAlternateBackground(TQColor());
  }
}

void ContactListView::setBackgroundPixmap(const TQString &filename)
{
  if (filename.isEmpty())
  {
    unsetPalette();
  }
  else
  {
    setPaletteBackgroundPixmap(TQPixmap(filename));
  }
}

void ContactListView::setShowIM( bool enabled )
{
  mShowIM = enabled;
}

bool ContactListView::showIM()
{
  return mShowIM;
}

void ContactListView::setIMColumn( int column )
{
  mInstantMsgColumn = column;
}

int ContactListView::imColumn()
{
  return mInstantMsgColumn;
}

#include "contactlistview.moc"
