/***************************************************************************
 *   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 "emovecmd.h"

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

// Elements
#include "elements/elementnode.h"
#include "elements/elementselection.h"
#include "elements/vectorelement.h"
#include "elements/vectorpath.h"
#include "elements/lengthattribute.h"
#include "elements/animatedlengthattr.h"
#include "elements/matrix.h"

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

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

EMoveCMD::EMoveCMD( int x, int y )
    : ECommand( i18n( "Move Elements" ) ),
    m_relX(x),
    m_relY(y)
{
  kdDebug() << k_funcinfo << endl;
  m_selection = Kast::self()->elementDB().selection().clone();
}

EMoveCMD::EMoveCMD( ElementNode * element, int x, int y )
    : ECommand( i18n( "Move Elements" ) ),
    m_relX(x),
    m_relY(y)
{
  m_selection = new ElementSelection();
  m_selection->append(*element, false);
}

EMoveCMD::~EMoveCMD()
{
  delete m_selection;
}

void EMoveCMD::execute()
{
  ECommand::execute();
  m_selection->elements().getFirst()->accept(*this);
}

void EMoveCMD::unexecute()
{
  ECommand::unexecute();
  Kast::self()->elementDB().selection() = *m_selection;
  m_selection->elements().getFirst()->accept(*this);
}

bool EMoveCMD::visit( VectorElement & element )
{
  if ( isExecuting() || isRedoing() )
    kdDebug() << "EMoveCMD::visit() (exec) - Moving by " << m_relX << "," << m_relY << "px" << endl;
  else
    kdDebug() << "EMoveCMD::visit() (exec) - Undoing move by " << m_relX << "," << m_relY << "px" << endl;

  unsigned int metaType = element.vectorPath().shapeMetaType();
  if (metaType == VectorPath::SHAPE_CIRCLE ||
      metaType == VectorPath::SHAPE_RECT   ||
      metaType == VectorPath::SHAPE_RRECT  ||
      metaType == VectorPath::SHAPE_ELLIPSE )
  {
//     // Map to matrix
//     Matrix *ctm = 0;
//     ctm = VConsolidateTransform::calcCTM(*m_selection->elements().getFirst());
//     int curX, curY;
//     ctm->qmatrix().invert().map(m_relX, m_relY, &curX, &curY);
//     delete ctm;
    if ( isExecuting() || isRedoing() )
    {
      double x = element.vectorPath().getX().baseVal().value();
      double y = element.vectorPath().getY().baseVal().value();
      element.vectorPath().getX().baseVal().newValueSpecifiedUnits(
        LengthAttribute::SVG_LENGTHTYPE_PX, x + m_relX );
      element.vectorPath().getY().baseVal().newValueSpecifiedUnits(
        LengthAttribute::SVG_LENGTHTYPE_PX, y + m_relY );
    }
    else
    {
      double x = element.vectorPath().getX().baseVal().value();
      double y = element.vectorPath().getY().baseVal().value();
      element.vectorPath().getX().baseVal().newValueSpecifiedUnits(
        LengthAttribute::SVG_LENGTHTYPE_PX, x - m_relX );
      element.vectorPath().getY().baseVal().newValueSpecifiedUnits(
        LengthAttribute::SVG_LENGTHTYPE_PX, y - m_relY );
    }
  }
  else if ( metaType == VectorPath::SHAPE_LINE)
  {
//     // Map to matrix
//     Matrix *ctm = 0;
//     ctm = VConsolidateTransform::calcCTM(*m_selection->elements().getFirst());
//     int curX, curY;
//     ctm->qmatrix().invert().map(m_relX, m_relY, &curX, &curY);
//     delete ctm;
    if ( isExecuting() || isRedoing() )
    {
      double x1 = element.vectorPath().getX1().baseVal().value();
      double y1 = element.vectorPath().getY1().baseVal().value();
      double x2 = element.vectorPath().getX2().baseVal().value();
      double y2 = element.vectorPath().getY2().baseVal().value();
      element.vectorPath().getX1().baseVal().newValueSpecifiedUnits(
        LengthAttribute::SVG_LENGTHTYPE_PX, x1 + m_relX );
      element.vectorPath().getY1().baseVal().newValueSpecifiedUnits(
        LengthAttribute::SVG_LENGTHTYPE_PX, y1 + m_relY );
      element.vectorPath().getX2().baseVal().newValueSpecifiedUnits(
        LengthAttribute::SVG_LENGTHTYPE_PX, x2 + m_relX );
      element.vectorPath().getY2().baseVal().newValueSpecifiedUnits(
        LengthAttribute::SVG_LENGTHTYPE_PX, y2 + m_relY );
    }
    else
    {
      double x1 = element.vectorPath().getX1().baseVal().value();
      double y1 = element.vectorPath().getY1().baseVal().value();
      double x2 = element.vectorPath().getX2().baseVal().value();
      double y2 = element.vectorPath().getY2().baseVal().value();
      element.vectorPath().getX1().baseVal().newValueSpecifiedUnits(
        LengthAttribute::SVG_LENGTHTYPE_PX, x1 - m_relX );
      element.vectorPath().getY1().baseVal().newValueSpecifiedUnits(
        LengthAttribute::SVG_LENGTHTYPE_PX, y1 - m_relY );
      element.vectorPath().getX2().baseVal().newValueSpecifiedUnits(
        LengthAttribute::SVG_LENGTHTYPE_PX, x2 - m_relX );
      element.vectorPath().getY2().baseVal().newValueSpecifiedUnits(
        LengthAttribute::SVG_LENGTHTYPE_PX, y2 - m_relY );
    }
  }
  else if ( metaType == VectorPath::SHAPE_POLYGON ||
            metaType == VectorPath::SHAPE_PATH)
  {
//     // Map to matrix
//     Matrix *ctm = 0;
//     ctm = VConsolidateTransform::calcCTM(*m_selection->elements().getFirst());
//     int curX, curY;
//     ctm->setE(0); ctm->setF(0); // Discard Translations
//     ctm->qmatrix().invert().map(m_relX, m_relY, &curX, &curY);
//     delete ctm;

    // Set new Path coords
    KCPathDataList* pathDataList = element.vectorPath().kcPathData();
    KCPathDataList::iterator it;
    for ( it = pathDataList->begin(); it != pathDataList->end(); ++it )
    {
      if ( isExecuting() )
      {
        (*it).x1 += m_relX;
        (*it).x2 += m_relX;
        (*it).x3 += m_relX;
        (*it).y1 += m_relY;
        (*it).y2 += m_relY;
        (*it).y3 += m_relY;
      }
      else
      {
        (*it).x1 -= m_relX;
        (*it).x2 -= m_relX;
        (*it).x3 -= m_relX;
        (*it).y1 -= m_relY;
        (*it).y2 -= m_relY;
        (*it).y3 -= m_relY;
      }
    }
  }

  element.setDirty();
  Kast::self()->elementDB().entryModified(&element);
  return true;
}
