/***************************************************************************
 *   Copyright (C) 2004 by Hans Oischinger                                 *
 *   hans.oischinger@kdemail.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 Steet, Fifth Floor, Boston, MA 02110-1301, USA.             *
 ***************************************************************************/
#include "documentwidget.h"

// Elements
#include "elements/documentelement.h"
#include "elements/vectorelement.h"
#include "elements/animateelement.h"

#include "elements/elementtreeiterator.h"
#include "elements/vectorpath.h"
#include "elements/animatedlengthattr.h"
#include "elements/lengthattribute.h"
#include "elements/elementselection.h"

// Visitors
#include "visitors/vsetanimvalues.h"
#include "visitors/vdrawelements.h"
#include "visitors/vconsolidatetransform.h"

// Core
#include "core/timeserver.h"
#include "core/direktorinstance.h"
#include "core/elementdatabase.h"

// Tools
#include "tools/toolmanager.h"

// KCanvas Headers
#include <kcanvas/KCanvas.h>
#include <kcanvas/device/KRenderingDevice.h>

// Qt
#include <qevent.h>
#include <qptrlist.h>

// KDE
#include <kdebug.h>
#include <kcursor.h>

// Nice value, from good-ol'-ksvg
#define ZOOM_FACTOR 1.2

DocumentWidget::DocumentWidget(QWidget *parent, const char *name)
    : CanvasWidget(parent, name)
{
  setMouseTracking(true);

  connect( &Kast::self()->timeServer(), SIGNAL(timeChanged()), SLOT(updateElementTree()));
  Kast::self()->elementDB().addElementListener(this);
  Kast::self()->elementDB().selection().addElementSelectionListener(this);
}


DocumentWidget::~DocumentWidget()
{}

void DocumentWidget::showEvent(QShowEvent *)
{
  updateElementTree();
}

void DocumentWidget::updateElementTree( ElementNode* root )
{
  if ( !m_canvas )
    return;

  if (root == 0)
    root = &Kast::self()->elementDB().documentRoot();
  ElementTreeIterator itr( root, true );

  //kdDebug() << "DocumentWidget::updateElementTree() - Starting VSetAnimValues" << endl;
  // First set the animValues to the current time
  itr.start();
  VSetAnimValues *vAnimTree = new VSetAnimValues();
  for( ; itr.current(); itr.next() )
    itr.current()->accept( *vAnimTree );
  delete vAnimTree;
  //kdDebug() << "DocumentWidget::updateElementTree() - VSetAnimValues finished " << endl;

  //kdDebug() << "DocumentWidget::updateElementTree() - Starting VDrawElements" << endl;
  // Draw the tree
  itr.start();
  bool setZindex = false;
  if ( root == &Kast::self()->elementDB().documentRoot() )
    setZindex = true;
  VDrawElements *vDrawTree = new VDrawElements( m_canvas, getDevice(), false, setZindex );

  for( ; itr.current(); itr.next() )
    itr.current()->accept( *vDrawTree );
  Kast::self()->elementDB().selection().accept( *vDrawTree );
  delete vDrawTree;
  //kdDebug() << "DocumentWidget::updateElementTree() - VDrawElements finished " << endl;

  //   m_canvas->/*drawDirtyChunks*/();
  //kdDebug() << "DocumentWidget::updateElementTree() - Update finished" << endl;
}

void DocumentWidget::updateElementSelection()
{
  if ( !m_canvas )
    return;

  VDrawElements *vDrawTree = new VDrawElements( m_canvas, getDevice() );
  Kast::self()->elementDB().selection().accept( *vDrawTree );
  delete vDrawTree;
}

void DocumentWidget::wheelEvent(QWheelEvent *event)
{
	if(event->delta() > 0)
		setZoom(zoom() * ZOOM_FACTOR, true);
	else
		setZoom(zoom() / ZOOM_FACTOR, true);

	event->accept();
}

void DocumentWidget::mouseMoveEvent(QMouseEvent *event)
{
  if(event->state() & RightButton && event->state() & ControlButton)
  {
    setCursor(KCursor::sizeAllCursor());

    QPoint diff = (event->pos() - m_firstPanPoint);
    //m_canvas->updatePan(diff - m_panPoint);
    m_panPoint = diff;
  }
  Kast::self()->toolManager().mouseEvent( event, event->pos() );

  event->accept();
}

void DocumentWidget::mousePressEvent(QMouseEvent *event)
{
  m_firstPanPoint = event->pos();
  Kast::self()->toolManager().mouseEvent( event, event->pos() );
  event->accept();
}

void DocumentWidget::mouseReleaseEvent(QMouseEvent *event)
{
  if(event->button() == RightButton)
  {
    setCursor(KCursor::arrowCursor());
    m_panPoint = QPoint(0, 0);
  }
  Kast::self()->toolManager().mouseEvent( event, event->pos() );

  event->accept();
}

void DocumentWidget::onElementRemoved( ElementNode* element )
{
  kdDebug() << k_funcinfo << endl;
  ElementTreeIterator itr( element, true );

  kdDebug() << "DocumentWidget::onElementRemoved() - Starting VDrawElements (remove only)" << endl;
  VDrawElements *vDrawTreeRemove = new VDrawElements( m_canvas, getDevice(), true );

//   if (element == &Kast::self()->elementDB().documentRoot())
//     reset();
//   else
//   {
    for( ; itr.current(); itr.next() )
      itr.current()->accept( *vDrawTreeRemove );
    delete vDrawTreeRemove;
//   }
}

void DocumentWidget::onElementInserted( ElementNode* e )
{
  kdDebug() << "DocumentWidget::onElementInserted() - " << e->className() << " ID:" << e->id() << endl;
  // Redraw

  //if (e == &Kast::self()->elementDB().documentRoot())
  //  reset();
  updateElementTree( e );
}

void DocumentWidget::onElementModified( ElementNode *e )
{
  kdDebug() << "DocumentWidget::onElementModified()" << endl;
  // Redraw
  updateElementTree( e );
}

void DocumentWidget::onSelectionModified( )
{
  kdDebug() << "DocumentWidget::onSelectionModified()" << endl;
  // Redraw
  updateElementSelection();
}



#include "documentwidget.moc"
