/***************************************************************************
**
**  This file is part of geopsy.
**
**  geopsy 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 3 of the License, or
**  (at your option) any later version.
**
**  geopsy 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 Foobar.  If not, see <http://www.gnu.org/licenses/>
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2004-03-07
**  Copyright: 2004-2019
**    Marc Wathelet
**    Marc Wathelet (ULg, Liège, Belgium)
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include <QPixmap>
#include <QWidget>
#include <QApplication>
#include <QDragEnterEvent>
#include <QMouseEvent>
#include <QDropEvent>

#include <GeopsyCore.h>
#include "SigSelectionDnD.h"

/*const char * SigSelectionDrag::format (int i) const
{
  if(i==0) return "geopsy/signalSelection"; else return 0;
}*/

SigSelectionDnD::SigSelectionDnD(QWidget * eventSource) :
    QObject(eventSource), _dropEnabled(true), _dragEnabled(true),
    _state(Idle), _filterEnabled(true)
{
  TRACE;
  _src=eventSource;
  _src->setAcceptDrops(true);
  _src->installEventFilter(this);
}

void SigSelectionDnD::enableFilter()
{
  TRACE;
  _filterEnabled=true;
}

void SigSelectionDnD::disableFilter()
{
  TRACE;
  _filterEnabled=false;
}

void SigSelectionDnD::setDropEnabled(bool b)
{
  TRACE;
  _dropEnabled=b;
  _src->setAcceptDrops(b);
}

bool SigSelectionDnD::eventFilter(QObject *, QEvent * e)
{
  TRACE;
  if( !_filterEnabled) return false;
  switch (e->type()) {
  case QEvent::DragEnter:
    return dragEnterEvent(static_cast<QDragEnterEvent *>(e));
  case QEvent::DragMove:
    return dragMoveEvent(static_cast<QDragMoveEvent *>(e));
  case QEvent::Drop:
    return dropEvent(static_cast<QDropEvent *>(e));
  case QEvent::MouseButtonPress:
    return mousePressEvent(static_cast<QMouseEvent *>(e));
  case QEvent::MouseButtonRelease:
    return mouseReleaseEvent(static_cast<QMouseEvent *>(e));
  case QEvent::MouseMove:
    return mouseMoveEvent(static_cast<QMouseEvent *>(e));
  default:
    return false;
  }
}

bool SigSelectionDnD::dragEnterEvent(QDragEnterEvent * e)
{
  TRACE;
  if(_dropEnabled && e->mimeData()->hasFormat("geopsy/x-signal-selection") && e->source()!=_src) {
    e->acceptProposedAction();
  }
  return true;
}

bool SigSelectionDnD::dragMoveEvent(QDragMoveEvent * e)
{
  TRACE;
  if(_dropEnabled && e->mimeData()->hasFormat("geopsy/x-signal-selection") && e->source()!=_src) {
    e->acceptProposedAction();
  }
  return true;
}

bool SigSelectionDnD::dropEvent(QDropEvent * e)
{
  TRACE;
  if(_dropEnabled && e->mimeData()->hasFormat("geopsy/x-signal-selection") && e->source()!=_src) {
    SubSignalPool * sel=*reinterpret_cast<SubSignalPool**>(e->mimeData()->data("geopsy/x-signal-selection").data());
    emit selectionDropped(_src, *sel);
  }
  e->acceptProposedAction();
  return true;
}

bool SigSelectionDnD::mousePressEvent(QMouseEvent * e)
{
  TRACE;
  if(_dragEnabled && e->buttons() & Qt::LeftButton) {
    _mousePressPos=e->pos();
    _state=Pressed;
  }
  return false;
}

bool SigSelectionDnD::mouseReleaseEvent(QMouseEvent * )
{
  TRACE;
  _state=Idle;
  return false;
}

bool SigSelectionDnD::mouseMoveEvent(QMouseEvent * e)
{
  TRACE;
  if(_dragEnabled && e->buttons() & Qt::LeftButton) {
    if(_state==Idle) {
      _mousePressPos=e->pos();
      _state=Pressed;
    } else if(_state==Pressed &&
                (e->pos()-_mousePressPos).manhattanLength()>QApplication::startDragDistance()) {
      SubSignalPool sel;
      emit getSelection(sel);

      QDrag *drag=new QDrag(_src);
      drag->setPixmap(QPixmap(":signaldnd.png"));
      QMimeData *mimeData=new QMimeData;
      QByteArray data;
      data.resize(sizeof(SubSignalPool *));
      *reinterpret_cast<SubSignalPool**>(data.data())=&sel;
      mimeData->setData("geopsy/x-signal-selection", data);
      drag->setMimeData(mimeData);

      _state=Dragging;
      drag->exec(Qt::CopyAction);
    }
    return true;
  }
  return false;
}


