/***************************************************************************
                          mylistview.cpp  -  description
                             -------------------
    begin                : Sat Jan 12 2002
    copyright            : (C) 2002 by Oliver Nölle
    email                :  yammi-developer@lists.sourceforge.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.                                   *
 *                                                                         *
 ***************************************************************************/

#include "mylistview.h"

#include <qheader.h>
#include <kdebug.h>

#include "yammigui.h"
#include "songlistitem.h"
#include "song.h"
#include "folder.h"


using namespace std;

extern YammiGui* gYammiGui;

MyListView::MyListView(QWidget *parent, const char *name ) : QListView(parent,name) {
    dragging=false;
    dontTouchFirst=false;
    sortedBy=0;
    oldSortOrder=0;
    this->parent=parent;
    setItemMargin(2);
    connect(this->header(), SIGNAL(clicked(int)), this, SLOT(sortColumnChanged(int)));
}

MyListView::~MyListView() {}

/**
 * Updates the sortedBy attribute when user changes sort column or order in listview.
 */
void MyListView::sortColumnChanged(int column) {
    int newColumn=column+1;
    if(sortOrder()==Qt::Descending) {
        sortedBy=-newColumn;
    } else {
        sortedBy=newColumn;
    }
}

void MyListView::simulateMouseMove() {
    // we simulate a mouse movement to keep list scrolling if we are above or below it
    QMouseEvent e(QEvent::MouseMove, dragPoint, 0, 0);
    contentsMouseMoveEvent(&e);
}


/**
 * Prepares for dragging, but dragging is only allowed if
 * - folder is sorted
 * - song list is sorted ascending by first column (which must be the "Pos" column)
 */
void MyListView::contentsMousePressEvent ( QMouseEvent * e) {
    if(gYammiGui->chosenFolder->isSorted() && sortedBy==1 && e->button()==LeftButton) {
        dragPoint=e->globalPos();
        dragItem=itemAt(viewport()->mapFromGlobal(dragPoint));
        if(dragItem) {
            //      cout << "dragItem found: " << ((SongListItem*)dragItem)->song()->displayName() << "\n";
            // check whether we allow dragging of first item
            if(!dontTouchFirst || dragItem!=firstChild()) {
                // start dragging
                //        cout << "dragging started\n";
                dragging=true;

                // do we have to disable sorting???
                // as we possibly move items not according sort order?
                // (can't move songs bug)
                oldSortOrder=sortedBy;
                setSorting(-1);

                dragStartedAtIndex=dragItem->itemPos();
                setCursor(Qt::sizeVerCursor);
                dragSong=((SongListItem*)dragItem)->song();
            }
        } else {
            //      cout << "no dragItem found\n";
        }
    }
    QListView::contentsMousePressEvent(e);
}


/**
 * called on dragging the mouse with button pressed
 */
void MyListView::contentsMouseMoveEvent ( QMouseEvent * e) {
    if(!dragging) {
        // if not dragging we call super class to perform normal behavior on dragging
        QListView::contentsMouseMoveEvent(e);
        return;
    }

    // dragging: check whether mouse has moved to new item
    QPoint point=e->globalPos();
    //  cout << "e->globalPos(): x: " << point.x() << ", y: " << point.y() << "\n";
    QPoint mappedPoint=viewport()->mapFromGlobal(point);
    /*  cout << "mappedPoint: x: " << mappedPoint.x() << ", y: " << mappedPoint.y() << "\n";
      QPoint widgetMappedPoint=mapFromGlobal(point);
      cout << "widgetMappedPoint: x: " << widgetMappedPoint.x() << ", y: " << widgetMappedPoint.y() << "\n";
      
      QPoint point2=QCursor::pos();
      cout << "QCursor::pos(): x: " << point2.x() << ", y: " << point2.y() << "\n";
      QPoint mappedPoint2=viewport()->mapFromGlobal(point2);
      cout << "mappedPoint2: x: " << mappedPoint.x() << ", y: " << mappedPoint.y() << "\n";
      QPoint widgetMappedPoint2=mapFromGlobal(point2);
      cout << "widgetMappedPoint2: x: " << widgetMappedPoint2.x() << ", y: " << widgetMappedPoint2.y() << "\n";
      */
    QListViewItem* item=itemAt(mappedPoint);
    /*  if(item!=0) {
    	  cout << "item: " << ((SongListItem*)item)->song()->displayName() << "\n";
      }
    	QListViewItem* item2=itemAt(widgetMappedPoint);
      if(item2!=0) {
    	  cout << "item2: " << ((SongListItem*)item2)->song()->displayName() << "\n";
      }
    	QListViewItem* item3=itemAt(mappedPoint2);
      if(item3!=0) {
    	  cout << "item3: " << ((SongListItem*)item3)->song()->displayName() << "\n";
      }
    	QListViewItem* item4=itemAt(widgetMappedPoint2);
      if(item4!=0) {
    	  cout << "item4: " << ((SongListItem*)item4)->song()->displayName() << "\n";
      }
    */

    // no valid item, mouse above or below listview?
    if(item==0)	{
        //    cout << "item==0\n";
        bool above=viewport()->mapFromGlobal(point).y()<0;
        QListViewItem* swapItem;
        if(above) {
            swapItem=dragItem->itemAbove();
            if(swapItem) {
                if(dontTouchFirst && swapItem==firstChild())
                    return;
                swapItem->moveItem(dragItem);
                ensureItemVisible(swapItem);
            }
        } else {
            swapItem=dragItem->itemBelow();
            if(swapItem)
                dragItem->moveItem(swapItem);
        }
        ensureItemVisible(dragItem);
        // keep scrolling, if mouse not moving...
        QTimer *timer = new QTimer( this );
        connect( timer, SIGNAL(timeout()), this, SLOT(simulateMouseMove()) );
        timer->start( 400, TRUE );
        return;
    }


    Song* s=((SongListItem*)item)->song();
    if(s==dragSong)	// item has not moved
        return;


    //  cout << "drag requested: \ndragSong: " << dragSong->displayName() << "\ns: " << s->displayName() << "\n";
    //  cout << "point.y(): " << point.y() << ", dragPoint.y(): " << dragPoint.y() << "\n";
    bool up=(point.y() < dragPoint.y());
    if(up) {		// don't allow dragging to top song (is played)
        if(dontTouchFirst && item==firstChild()) {
            //			cout << "dragging to top song not allowed in this folder!\n";
            return;
        }
    }

    //  cout << "moving item!\n";
    dragItem->moveItem(item);
    if(up) {
        dragItem->itemAbove()->moveItem(dragItem);
    }
    dragPoint=point;
}


/**
 * Called on release of mouse button, possibly end of dragging a song.
 */
void MyListView::contentsMouseReleaseEvent ( QMouseEvent * e) {
    if(dragging) {
        dragging=false;
        setCursor(Qt::arrowCursor);
        // check, whether item really moved to new position
        if(dragItem->itemPos()!=dragStartedAtIndex) {
            gYammiGui->stopDragging();			// only invoke this, if dragSong was moved
        }
        // reset sort order (can't move songs bug)
        bool asc=oldSortOrder>0;
        if(!asc) {
            oldSortOrder=-oldSortOrder;
        }
        int column=oldSortOrder-1;
        setSorting(column);
    }
    QListView::contentsMouseReleaseEvent(e);
}

void MyListView::simulateKeyPressEvent(QKeyEvent* e)
{
    keyPressEvent(e);
}

