/*
 * MoveCommand.cpp
 *
 * Copyright (C) 1999 Stephen F. White
 * 
 * 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 (see the file "COPYING" for details); if 
 * not, write to the Free Software Foundation, Inc., 675 Mass Ave, 
 * Cambridge, MA 02139, USA.
 */

#include <stdio.h>
#include "stdafx.h"

#include "MoveCommand.h"
#include "Scene.h"
#include "Node.h"
#include "FieldValue.h"
#include "SFNode.h"
#include "MFNode.h"
#include "Path.h"
#include "DuneApp.h"

MoveCommand::MoveCommand(Node *node, Node *src, int srcField, 
                         Node *dest, int destField, int destIndex)
{
    _node = node;

    _src = src;
    _srcField = srcField;
    _dest = dest;
    _destField = destField;
    _failed = false;

    if (_src) {
        _oldValueSrc = _src->getField(_srcField);
        _oldValueSrc->ref();
        _newValueSrc = _oldValueSrc->removeNode(node);
        if (_newValueSrc == NULL) {
            _failed = true;
            return;
        }
        _newValueSrc->ref();
    } else {
        _oldValueSrc = _newValueSrc = NULL;
    }

    if (_dest) {
        _oldValueDest = _dest->getField(_destField);
        _oldValueDest->ref();
        _newValueDest = _oldValueDest->addNode(node, destIndex);
        _newValueDest->ref();
    } else {
        _oldValueDest = _newValueDest = NULL;
    }
}

MoveCommand::~MoveCommand()
{
    if (_src) {
        _oldValueSrc->unref();
        _newValueSrc->unref();
    }
    if (_dest) {
        _oldValueDest->unref();
        _newValueDest->unref();
    }
}

void
MoveCommand::execute()
{
    if (_failed)
        return;
    const Path *selection = _node->getScene()->getSelection();
    if (selection && (_node == selection->getNode())) {
        if ((_dest == NULL) && _node->hasParent()) {
            _node->getScene()->setSelection(_node->getParent());
            TheApp->removeClipboardNode(_node);
        } else
            _node->getScene()->setSelection(_node);
        _node->getScene()->UpdateViews(NULL, UPDATE_SELECTION);
    }
    if (_src) {
        _src->setField(_srcField, _newValueSrc);
        MyString nodeName = "";
        if (_node->hasName())
            nodeName += _node->getName();
        _node->getScene()->OnRemoveNode(_node, _src, _srcField);
        _node->getScene()->def(nodeName, _node);
    }
    if (_dest) {
        MyString nodeName = "";
        if (_node->hasName())
            nodeName += _node->getName();
        _dest->setField(_destField, _newValueDest);
        _node->getScene()->def(nodeName, _node);
        _node->getScene()->OnAddNode(_node, _dest, _destField);
    } 
}

void
MoveCommand::undo()
{
    _node->getScene()->setSelection(_node);
    _node->getScene()->UpdateViews(NULL, UPDATE_SELECTION);
    MyString nodeName = "";
    if (_node->hasName())
        nodeName += _node->getName();
    if (_dest) {
        _dest->setField(_destField, _oldValueDest);
        _node->getScene()->def(nodeName, _node);
        _node->getScene()->OnRemoveNode(_node, _dest, _destField);
    }
    if (_src) {
        _src->setField(_srcField, _oldValueSrc);
        _node->getScene()->def(nodeName, _node);
        _node->getScene()->OnAddNode(_node, _src, _srcField);
    } 
}
