/*
* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
*
*/


#include "WebChromeItem.h"
#include "ChromeWidget.h"
#include "ChromeRenderer.h"
#include "ChromeDOM.h"
#include "WebChromeSnippet.h"
#ifndef NO_QSTM_GESTURE
#include "qstmgestureevent.h"
#endif
#include <QSizePolicy>
#include <QWebHitTestResult>
#include <QWebFrame>
#include <QGraphicsView>
#include <QDebug>

namespace GVA {
#ifndef NO_QSTM_GESTURE
using namespace qstmGesture;
#endif
  WebChromeItem::WebChromeItem(const QRectF& ownerArea, ChromeWidget *chrome, const QWebElement & element, QGraphicsItem* parent)
    : QGraphicsWidget(parent),
      m_ownerArea(ownerArea),
      m_chrome(chrome),
      m_element(element),
      m_painting(false)
  {

    
    // G1: Prevent hover events from passing through to the underlying widget.
    //setAcceptHoverEvents(true); ?

    //setFocusPolicy(Qt::ClickFocus);
    //setOpacity(0.50);
    //Set preferred size so item will resize as part of anchor layout
    setFlags(QGraphicsItem::ItemIsFocusable);
    setPreferredSize(ownerArea.width(), ownerArea.height());
    //Also resize in case item is not part of anchor layout
    resize(preferredSize());
#ifndef NO_QSTM_GESTURE
    grabGesture(QStm_Gesture::assignedType());
#endif
    //Use QGraphicsScene cached rendering NB: This might degrade rendering quality for some animation transforms
    setCacheMode(QGraphicsItem::ItemCoordinateCache);
  }

  WebChromeItem::~WebChromeItem()
  {

  }

  void WebChromeItem::init(WebChromeSnippet * snippet)
  {
    setCachedHandlers(chrome()->dom()->getCachedHandlers(snippet->elementId(), ownerArea()));

    //QObject::connect(
    //        renderer(),
    //        SIGNAL(chromeRepainted(const QRectF&)),
    //        this,
    //        SLOT(repaintFromChrome(const QRectF&))/*, Qt::QueuedConnection*/);
  

    //When chrome is resized owner areas for snippets may change
    //NB: Maybe this needs to be done on chromeRepainted too?
    QObject::connect(
            renderer(),
            SIGNAL(chromeResized()),
            snippet,
            SLOT(updateOwnerArea()));


    QObject::connect(
            this,
            SIGNAL(contextMenu(QGraphicsSceneContextMenuEvent *)),
            snippet,
            SLOT(onContextMenuEvent(QGraphicsSceneContextMenuEvent *)));
  }

  QGraphicsScene * WebChromeItem::scene()
  {
    return m_chrome->getScene();
  }

  ChromeRenderer * WebChromeItem::renderer()
  {
    return m_chrome->renderer();
  }

  void WebChromeItem::setOwnerArea(const QRectF& ownerArea)
  {
    m_ownerArea = ownerArea;
    //Set preferred size so item will resize as part of anchor layout
    setPreferredSize(ownerArea.width(), ownerArea.height());
    //Also resize in case item is not part of anchor layout
    resize(preferredSize());
  }

  //NB: Not used. Updates now come from renderer directly
  void WebChromeItem::repaintFromChrome(const QRectF & rect) // slot
  {
    QPainter painter;
    Q_UNUSED(rect)
    qDebug() << "WebChromeItem::repaintFromChrome: dirtyRect: " << rect << " ownerArea: " << m_ownerArea << " elemGeom: " << m_element.geometry();
    // Update if this is our rect
      if(rect.intersects(m_ownerArea))
       update();
  }

  // NB: For now we only handle onclick (actually mouseUp). Fix this
  // NB: Modify for multiple cached handlers: mouse click, long press
  // and support handlers not executed in js engine.

  void WebChromeItem::cachedHandlerEvent(QGraphicsSceneMouseEvent * ev)
  {
    for(int i = 0; i < m_handlers.size(); i++){
     const CachedHandler & handler = m_handlers.at(i);
      if(handler.rect().contains(ev->pos())){
	qDebug() << "Invoking cached handler: " << handler.script();
        //m_chrome->evalWithEngineContext(handler.script());
	handler.invoke();
        return;
      }
    }
  }

  void WebChromeItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* opt, QWidget* widget)
  {
    Q_UNUSED(opt)
    Q_UNUSED(widget)
      //For debugging
    //painter->fillRect(QRectF(0,0, m_ownerArea.width(), m_ownerArea.height()), Qt::yellow);
    qDebug() << " WebChromeItem::paint: " << m_element.attribute("id"); 
    m_painting = true;
    m_element.render(painter);
    m_painting = false;
  }
 

  void WebChromeItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * ev)
  {

    // qDebug() << "ChromeRenderer::contextMenuEvent";
    ev->setAccepted(true);
    //Signal context menu event
    emit contextMenu(ev);
  }

  void WebChromeItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent * ev)
  {
    
    forwardMouseEvent(QEvent::MouseButtonDblClick, ev);
  }
  
  void WebChromeItem::grabFocus()
  {
    setFocusProxy(m_chrome->renderer());
    setFocus();
  }

  void WebChromeItem::mousePressEvent(QGraphicsSceneMouseEvent * ev)
  {
    //On mouse press, first invoke any cached handlers. 
    cachedHandlerEvent(ev);
    //Then do normal mouse press handling
    setFocus();
    setFocusProxy(m_chrome->renderer());
    forwardMouseEvent(QEvent::MouseButtonPress, ev);
  }
  
  void WebChromeItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * ev)
  {
    forwardMouseEvent(QEvent::MouseButtonRelease, ev);
#if defined __SYMBIAN32__
// FIXME Remove this, it will be fixed Qt 4.6.3 ? 
    if (ev->button() == Qt::LeftButton) {
        QPoint p = QPoint(int(m_ownerArea.x()), int(m_ownerArea.y())) + ev->pos().toPoint();
        QWebFrame* frame = m_chrome->renderer()->page()->mainFrame();
        QWebHitTestResult htr = frame->hitTestContent(p);
        if (htr.isContentEditable()) {
            QEvent vkbEvent(QEvent::RequestSoftwareInputPanel);
            QList<QGraphicsView*> views = m_chrome->renderer()->scene()->views();
            QWidget* view = qobject_cast<QWidget*>(views.value(0));
            if (view)
              QApplication::sendEvent(view, &vkbEvent);
        }
    }
#endif
  }

  
  void WebChromeItem::mouseMoveEvent(QGraphicsSceneMouseEvent * ev)
  {
    forwardMouseEvent(QEvent::MouseMove, ev);
  }

  
  void WebChromeItem::forwardMouseEvent(QEvent::Type type, QGraphicsSceneMouseEvent *ev) {
   
    emit mouseEvent(type);
    // m_chrome->renderer()->setFocus();
    QMouseEvent shiftedEv( type, QPoint(int(m_ownerArea.x()), int(m_ownerArea.y()))+ev->pos().toPoint(),
			   ev->button(), ev->buttons(), ev->modifiers() );
    //qDebug() << "m_ownerArea: " << m_ownerArea << "ev->pos(): " << ev->pos() << 
    //		"shiftedEv.pos(): " << shiftedEv.pos();
    QApplication::sendEvent(m_chrome->renderer()->page(),&shiftedEv);
  }
  
  void WebChromeItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event ) {
    // Translate to a mouse move event.
    QMouseEvent shiftedEv( QEvent::MouseMove, QPoint(int(m_ownerArea.x()), int(m_ownerArea.y()))+event->pos().toPoint(),
			   Qt::NoButton, Qt::NoButton, Qt::NoModifier);
    QApplication::sendEvent(m_chrome->renderer(), &shiftedEv);
  }
  /* 
  void WebChromeItem::keyPressEvent ( QKeyEvent * event ) {
    qDebug() << "WebChromeItem: keyPressEvent " << event->type();
    QApplication::sendEvent(m_chrome->renderer(), event);
  }
  
  void WebChromeItem::keyReleaseEvent ( QKeyEvent * event ) {
    qDebug() << "WebChromeItem: keyReleaseEvent " << event->type();
    QApplication::sendEvent(m_chrome->renderer(), event);
  }
  */
  
  bool WebChromeItem::event(QEvent* event)
  {
#ifndef NO_QSTM_GESTURE
	  if (event->type() == QEvent::Gesture) {
	      QStm_Gesture* gesture = getQStmGesture(event);
	      if (gesture) {
	          QStm_GestureType gtype = gesture->getGestureStmType();
	      	  if (gtype == QStmTouchGestureType || gtype == QStmReleaseGestureType) {
	      		  gesture->sendMouseEvents();
	              return true;
	          }  
	      }
	  }
#endif
	  return QGraphicsWidget::event(event);
  }
  
} // endof namespace GVA
