/***************************************************************************
*   Copyright (C) 2006 - 2008 Robert Hogan                                *
*   robert@roberthogan.net                                                *
 *                                                                         *
 *   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 St, Fifth Floor, Boston, MA 02110-1301, USA.              *
 ***************************************************************************/

#include "dndlistview.h"
#include "torkconfig.h"
#include "kdebug.h"
#include <qapplication.h>
#include <qheader.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kstandarddirs.h>

#include <qsimplerichtext.h>
#include <qpainter.h>

DndListView::DndListView( QWidget * parent, const char * name, WFlags f ) :
    QListView( parent, name, f ), oldCurrent( 0 ),
      dropItem( 0 ), mousePressed( FALSE ),m_recentDrop( FALSE)
{

    setAllColumnsShowFocus( TRUE );
    //setResizeMode( QListView::AllColumns );
    setSelectionMode( QListView::Extended );

    setAcceptDrops( TRUE );
    viewport()->setAcceptDrops( TRUE );

}


//static const int autoopenTime = 750;


void DndListView::contentsDragEnterEvent( QDragEnterEvent *e )
{

    setSelectionMode( QListView::Single );

    if ( !QTextDrag::canDecode( e ) ) {
        e->ignore();
        return;
    }

    oldCurrent = currentItem();

    QListViewItem *i = itemAt( contentsToViewport(e->pos()) );
    if ( i ) {
        dropItem = i;
/*        autoopen_timer->start( autoopenTime );*/
    }
}


void DndListView::contentsDragMoveEvent( QDragMoveEvent *e )
{
    if ( !QTextDrag::canDecode( e ) ) {
        e->ignore();
        return;
    }
    QPoint vp = contentsToViewport( ( (QDragMoveEvent*)e )->pos() );
    QListViewItem *i = itemAt( vp );

       //!(e->source() == this) && 

    if ((QString(this->name()).contains("circuitList")) &&
       (QString(e->source()->name()).contains("serverList"))) {

        if ( i ){
            setSelected( i, TRUE );
            if ( i != dropItem ) {
                dropItem = i;
            }
        }
        e->accept(); 
    }else if ((QString(this->name()).contains("circuitList")) &&
       (QString(e->source()->name()).contains("circuitList"))) {
        if ( i ){
            setSelected( i, TRUE );
            if ( i != dropItem ) {
                dropItem = i;
            }
        }
        e->accept();
    }else if ((QString(this->name()).contains("circuitList")) &&
       (QString(e->source()->name()).contains("ORList"))) {
        if ( i ){
            setSelected( i, TRUE );
            if ( i != dropItem ) {
                dropItem = i;
            }
        }
        e->accept();
    }else if ((QString(this->name()).contains("circuitList")) &&
       (QString(e->source()->name()).contains("streamList"))) {
        if ( i ){
            setSelected( i, TRUE );
            if ( i != dropItem ) {
                dropItem = i;
            }
        }
        e->accept();

    }else {
        e->ignore();
        dropItem = 0;
    }
}

void DndListView::contentsDragLeaveEvent( QDragLeaveEvent * )
{
/*    autoopen_timer->stop();*/

    dropItem = 0;

    setCurrentItem( oldCurrent );
    setSelected( oldCurrent, TRUE );

    setSelectionMode( QListView::Extended );

}

void DndListView::contentsDropEvent( QDropEvent *e )
{
//     autoopen_timer->stop();
    m_recentDrop = true;
    dropTimer = startTimer( 3000 );
    
    setSelectionMode( QListView::Extended );

    QString text;
    if ( !QTextDrag::decode( e, text ) ) {
        e->ignore();
        return;
    }

    m_mousepos = e->pos() ;

    QListViewItem *item = itemAt( contentsToViewport(e->pos()) );
    if (QString(this->name()).contains("circuitList")){
        e->accept();
        if ( item ) {
            if (QString(e->source()->name()).contains("serverList"))
                emit extendCircuit(item->text(0),text,true);
            else if (QString(e->source()->name()).contains("circuitList"))
                emit extendCircuit(item->text(0),text, true);
            else if (QString(e->source()->name()).contains("ORList")) 
                emit extendCircuit(item->text(0),text, false);
            else if (QString(e->source()->name()).contains("streamList"))
                emit attach(item->text(0),text);
        } else{
            if (QString(e->source()->name()).contains("serverList")) 
                emit createCircuit(text,true);
            else if (QString(e->source()->name()).contains("ORList"))
                emit createCircuit(text,false);
        }
    }else
        e->ignore();

}



void DndListView::contentsMousePressEvent( QMouseEvent* e )
{
    QPoint p( contentsToViewport( e->pos() ) );
    //QListViewItem *i = itemAt( p );
/*    if ( i ) {
        // if the user clicked into the root decoration of the item, don't try to start a drag!
        if ( p.x() > header()->cellPos( header()->mapToActual( 0 ) ) +
             treeStepSize() * ( i->depth() + ( rootIsDecorated() ? 1 : 0) ) + itemMargin() ||
             p.x() < header()->cellPos( header()->mapToActual( 0 ) ) ) {
            presspos = e->pos();
            mousePressed = TRUE;
        }
    }*/

    if (e->button() == Qt::LeftButton){
        presspos = e->pos();
        mousePressed = TRUE;
    }
    QListView::contentsMousePressEvent( e );
}

void DndListView::contentsMouseMoveEvent( QMouseEvent* e )
{
    if ( mousePressed  ) {
        kdDebug() << "in mouse move drag" << endl;

        mousePressed = FALSE;
        //QListViewItem *item = itemAt( contentsToViewport(presspos) );

        int column;
        if (QString(this->name()).contains("circuitList"))
            column = 2;
        else if (QString(this->name()).contains("ORList"))
            column = 1;
        else if (QString(this->name()).contains("streamList"))
            column = 0;
        else
            column = 2;

        QString selectedItems;
        QListViewItemIterator it(this, QListViewItemIterator::Selected);
        while ( it.current() ) {
            if (this->isSelected( it.current()))
                selectedItems.append(it.current()->text(column)+" ");
            ++it;
        }
        if (!selectedItems.isEmpty()){
            selectedItems = selectedItems.stripWhiteSpace();
            QDragObject *d = new QTextDrag( selectedItems, this );
            d->dragCopy(); // do NOT delete d.
        }

    }else
        QListView::contentsMouseMoveEvent( e );
}

void DndListView::contentsMouseReleaseEvent( QMouseEvent* e)
{
/*    kdDebug() << "mouse released" << endl;*/
    mousePressed = FALSE;
    QListView::contentsMouseReleaseEvent(e);

}

void DndListView::mouseReleaseEvent( QMouseEvent* e)
{
/*    kdDebug() << "mouse released" << endl;*/
    mousePressed = FALSE;
    QListView::mouseReleaseEvent(e);

}

QPoint DndListView::getMousePos()
{
    return m_mousepos;
}

void DndListView::timerEvent( QTimerEvent * )
{
    //if ( e->timerId() == dropTimer )        // stop showing date
    m_recentDrop = false;
    killTimer( dropTimer );
    dropTimer = -1;
}



void
DndListView::viewportPaintEvent( QPaintEvent *e )
{
    QListView::viewportPaintEvent( e );

    if (!TorkConfig::displayBubble())
        return;
    // Superimpose bubble help
    // Taken from mediabrowser.cpp in Amarok

    if (( childCount() == 0 ) && (QString(this->name()).contains("streamList")))
    {
        QPainter p( viewport() );

        QSimpleRichText t( i18n(
                "<div align=center>"
                  "<h4>Almost Everything Is Clickable.</h4>"
                    "You can drag servers to create circuits. You can drag connections onto circuits "
                    " if you right-click here first. "
                    "You can right-click on servers to include/exclude them or their country from your "
                    "connections. Remember though: <b> messing with stuff is fun, but generally bad for "
                    "anonymity.</b>" 
                "</div>" ), QApplication::font() );

        t.setWidth( width() - 50 );

        const uint w = t.width() + 20;
        const uint h = t.height() + 20;

        p.setBrush( colorGroup().background() );
        p.drawRoundRect( 15, 15, w, h, (8*200)/w, (8*200)/h );
        t.draw( &p, 20, 20, QRect(), colorGroup() );
    }
}


// QDragObject *DndListView::dragObject()
// {
//     kdDebug() << "dragging item" << endl;
//     return new QTextDrag( currentItem()->text(0), this );
// }


// void DndListView::dragEnterEvent( QDragEnterEvent *evt )
// {
//     kdDebug() << "drag enter event" << endl;
//     if ( QTextDrag::canDecode( evt ) ) 
// 	   evt->accept();
// }
// 
// 
// void DndListView::dropEvent( QDropEvent *evt )
// {
//     QString text;
// 
//     if ( QTextDrag::decode( evt, text ) ) 
// 	       kdDebug() << text << endl;
// }
// 
// 
// void DndListView::contentsMousePressEvent( QMouseEvent *evt )
// {
//     dragging = TRUE;
//     kdDebug() << "draggng mouse" << endl;
//     QListView::mousePressEvent( evt );
// 
// }
// 
// 
// void DndListView::contentsMouseMoveEvent( QMouseEvent * )
// {
//     if ( dragging ) {
//         kdDebug() << "dragging" << endl; 
//         QDragObject *d = new QTextDrag( currentItem()->text(0), this );
//         d->dragCopy(); // do NOT delete d.
//         dragging = FALSE;
//     }
// }

#include "dndlistview.moc"
