/*****************************************************************************
 *
 * Copyright (C) 2021  Wilhelm Hagemeister <hm@igh.de>
 *
 * This file is part of the DLS widget library.
 *
 * The DLS widget library is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * The DLS widget library 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 Lesser
 * General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with the DLS widget library. If not, see
 * <http://www.gnu.org/licenses/>.
 *
 *
 * see: https://www.qcustomplot.com/index.php/support/forum/1431
 *
 * https://gitlab.com/vikingsoftware/blog-qobject-serialize
 *
 * !!!This code is experimental and can be used as an example on how to
 * integrate the C++ dlswidgets in qml.
 *
 ***************************************************************************/

#include <QObject>
#include <QPainter>
#include <QApplication>
#include <QDebug>
#include <QRectF>
#include <QtMath>
#include <QCoreApplication>
#include <QRect>

#include "dlswidget.h"

/* --------------------------------------------------------------------------------- */

DlsWidget::DlsWidget(QQuickItem *parent)
  : QQuickPaintedItem(parent)


{

  //qDebug() << "init";
  setAcceptedMouseButtons(Qt::AllButtons);
  setAcceptHoverEvents(true);
  setAcceptTouchEvents(true);
  //setFlag(ItemAcceptsInputMethod, true);

  //setMouseTracking(true);
  //this is not possible; QQuickPaintedItem does not inherit QWidget

  //DLS-Graph
  dlsGraph.setDropModel(&dlsModel);

  dlsGraph.load("./demo2.dlsv",&dlsModel);

  //grab events from dlsGraph
  dlsGraph.installEventFilter(this);

  this->setImplicitWidth(1000);
  this->setImplicitHeight(600);
  connect(&dlsGraph,SIGNAL(asyncUpdate()),this,SLOT(dlsGraphUpdated()));

}

/* --------------------------------------------------------------- */
/* DlsWidget events get forwarded to dlsGraph */

bool DlsWidget::event(QEvent *event)
{
  //qDebug() << "DlsWidgets Event" << event->type();
  //redirect events to the dlsGraph
  //basically working... we have to catch the events from dlsGraph, to
  //act on them (popup, redraw,....)
  bool ret = false;
  //reroute (qml) hover event to mouse move event
  if (event->type() == QEvent::HoverMove) {
    QHoverEvent *hoverEvent = static_cast<QHoverEvent *>(event);
    QMouseEvent* newEvent = new QMouseEvent(QEvent::MouseMove,
					    hoverEvent->posF(),
					    Qt::NoButton,
					    Qt::NoButton,
					    hoverEvent->modifiers());
    
    QCoreApplication::postEvent(&dlsGraph,newEvent);
    ret = true;
    //update(QRect(0,0,this->width(),this->height()));
  }

  if(QCoreApplication::sendEvent(&dlsGraph,event)) {
    ret = true;
  }

  if(ret) {
    update(QRect(0,0,this->width(),this->height()));
    return true;
  }

  return QObject::event(event);
}

/* --------------------------------------------------------------------------------- */
/* vice versa
 * send dlsGraph-events to dlsWidget
 */

bool DlsWidget::eventFilter(QObject *obj, QEvent *event)
  {
    //qDebug() << "DLSGraph Events " << event->type();
    
    if (event->type() == QEvent::CursorChange) {
      //qDebug() << "Cursor";
      setCursor(dlsGraph.cursor());
      return true;
    }
    /* does not work because the widget is not visible */
    /*
    if (event->type() == QEvent::UpdateRequest) {
      qDebug() << "Paint";
      update(QRect(0,0,this->width(),this->height()));
      return true;
    }
    */
      
    return QObject::eventFilter(obj, event);
  }
/*
      if (event->type() == QEvent::KeyPress) {
          QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
          qDebug("Ate key press %d", keyEvent->key());
          return true;
      } else {
          // standard event processing
          return QObject::eventFilter(obj, event);
      }
  }
*/
/* --------------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------------- */

void DlsWidget::dlsGraphUpdated() {
    update(QRect(0,0,this->width(),this->height()));
}

/* --------------------------------------------------------------------------------- */

void DlsWidget::paint(QPainter *painter) {

  QPixmap pixmap = QPixmap(QSize(this->width(),this->height()));
  pixmap.fill(Qt::transparent);
  
  dlsGraph.setMinimumWidth(this->width());
  dlsGraph.setMinimumHeight(this->height());
  dlsGraph.setMaximumWidth(this->width());
  dlsGraph.setMaximumHeight(this->height());

  dlsGraph.render(&pixmap);
  
  painter->drawPixmap(0,0, pixmap);

}

/* --------------------------------------------------------------------------------- */

void DlsWidget::actionTrigger(QString t){
  //this function is called from qml with the objectName of the action (see Graph.cpp)
  QMenu *menu = dlsGraph.getMenu();
  QList<QAction *> actions = menu->actions();

  foreach(QAction *action,actions) {
    if (action->menu()) {  //ok, action is submenu
                           //we only have one depth, so no recursion here!
      QList<QAction *> subMenuActions = action->menu()->actions();
      foreach(QAction *subAction,subMenuActions) {
	if (t == subAction->objectName()) {
	  subAction->trigger();
	  break;
	}
      }
    }
    if (t == action->objectName()) {
      action->trigger();
      break;
    }
  }
}

