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

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

// Elements
#include "elements/elementnode.h"
#include "elements/elementselection.h"
#include "elements/vectorelement.h"
#include "elements/animatedlengthattr.h"
#include "elements/matrix.h"
#include "elements/transformlist.h"
#include "elements/animatedtransformlist.h"
#include "elements/animateelement.h"
#include "elements/urireference.h"
#include "elements/timeattribute.h"

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

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

ETransformCMD::ETransformCMD( Transform* transform )
    : ECommand( i18n( "Transform Elements" ) ),
    m_removed(0)
{
  kdDebug() << k_funcinfo << endl;
  m_tlist = new TransformList();
  m_tlist->append(transform);
  m_selection = Kast::self()->elementDB().selection().clone();
}

ETransformCMD::ETransformCMD( TransformList* transformlist )
    : ECommand( i18n( "Transform Elements" ) ),
    m_tlist(transformlist),
    m_removed(0)
{
  kdDebug() << k_funcinfo << endl;
  m_selection = Kast::self()->elementDB().selection().clone();
}

ETransformCMD::ETransformCMD( ElementNode* element, Transform* transform )
    : ECommand( i18n( "Transform Elements") ),
    m_removed(0)
{
  kdDebug() << k_funcinfo << endl;
  m_tlist = new TransformList();
  m_tlist->append(transform);
  m_selection = new ElementSelection();
  m_selection->append(*element, false);
}

ETransformCMD::~ETransformCMD()
{
  if (m_removed)
  {
    QPtrListIterator<AnimateTransformElement> it( m_animlist );
    AnimateTransformElement *e;
    while ( (e = it.current()) != 0 )
    {
      Kast::self()->elementDB().deleteEntry( e );
      ++it;
    }

    delete m_tlist;
  }

  delete m_selection;
}

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

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

bool ETransformCMD::visit( VectorElement & element )
{
  if ( isExecuting() )
    kdDebug() << "ETransformCMD::visit() (exec) - " << endl;
  else
    kdDebug() << "ETransformCMD::visit() (exec) - " << endl;

  if ( getRecordAnimation() )
  {
    if ( isExecuting() )
    {
      // Redo
      if (!m_animlist.isEmpty())
      {
        QPtrListIterator<AnimateTransformElement> it( m_animlist );
        AnimateTransformElement *e;
        while ( (e = it.current()) != 0 )
        {
          ++it;
          Kast::self()->elementDB().reviveEntry(e);
        }
        m_removed = false;
      }
      else
      {
        for(unsigned int i = 0; i < m_tlist->count(); ++i)
        {
          URIReference *ref = new URIReference( &element, true );
          AnimateTransformElement* animTransElement =
            new AnimateTransformElement(*ref, &element.transformList());
          animTransElement->setFill( AnimateElement::FILL_FREEZE );
          //animTransElement->fromAttribute() = ;
          //animTransElement->byAttribute() = byAttr;
          animTransElement->toAttribute() = *m_tlist->at(i);
          animTransElement->getStartTime().setValue( 0.0 );
          animTransElement->getSimpleDuration().setValue( Kast::self()->timeServer().getTime() );
          element.appendChild(animTransElement);
          Kast::self()->elementDB().insertEntry(animTransElement);
          m_animlist.append(animTransElement);

          kdDebug() << "ETransformCMD::visit() - Appended animateTransform (to: " << animTransElement->toAttribute().getReadableTransformMetaType() << ") (by: " << animTransElement->byAttribute().getReadableTransformMetaType() << ")" << endl;
        }
      }
    }
    else
    {
      if ( !m_animlist.isEmpty() )
      {
        QPtrListIterator<AnimateTransformElement> it( m_animlist );
        AnimateTransformElement *e;
        while ( (e = it.current()) != 0 )
        {
          ++it;
          Kast::self()->elementDB().removeEntry(e);
        }
        m_removed = true;
      }
    }
  }
  else
  {
    if ( isExecuting() )
    {
      for(unsigned int i = 0; i < m_tlist->count(); i++)
        element.transformList().baseVal().append( m_tlist->at(i) );
    }
    else
    {
      if ( !m_tlist->isEmpty() )
      {
        // Take the element back from the list (remove would delete it throught autoDelete)
        for(unsigned int i = 0; i < m_tlist->count(); i++)
        {
          element.transformList().baseVal().findRef( m_tlist->at(i) );
          element.transformList().baseVal().take();
        }
      }
    }
  }

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


