#include "compositecommand.h"

#include "data/project.h"
#include "uisocket.h"
#include "mainwindow.h"

#include "editing/projectcommands.h"
#include "editing/patterncommands.h"

#include <QDebug>

using Xybrid::Data::Project;
using Xybrid::Data::Pattern;
using namespace Xybrid::Editing;

CompositeCommand::CompositeCommand(std::shared_ptr<Project> p) {
    project = p;
}

CompositeCommand* CompositeCommand::reserve(int count) {
    if (count <= 0) return this;
    children.reserve(static_cast<size_t>(count));
    return this;
}

CompositeCommand* CompositeCommand::compose(ProjectCommand* c) {
    if (!project) {
        project = c->project;
    } else if (c->project != project && !c->cancel()) return this; // fail
    c->composed = true;
    if (!children.empty() && children.back()->mergeWith(c)) c->cancel();
    else children.emplace_back(c);
    return this;
}
CompositeCommand* CompositeCommand::compose(PatternCommand* c) {
    if (!project) {
        project = c->pattern->project->socket->window->getProject();
    } else if (c->pattern->project != project.get() && !c->cancel()) return this; // fail
    if (!pattern) pattern = c->pattern;
    c->composed = true;
    if (!children.empty() && children.back()->mergeWith(c)) c->cancel();
    else children.emplace_back(c);
    return this;
}

bool CompositeCommand::commit(QString name) {
    if (!project || !project->socket || !project->socket->undoStack) return cancel();
    if (children.empty()) return cancel(); // no children? no action
    if (!name.isEmpty()) setText(name);
    project->socket->undoStack->push(this);
    return true;
}
bool CompositeCommand::cancel() {
    delete this;
    return false;
}

void CompositeCommand::redo() {
    for (auto i = children.begin(); i != children.end(); i++) (*i)->redo();
    if (pattern) emit project->socket->patternUpdated(pattern.get());
}

void CompositeCommand::undo() {
    for (auto i = children.rbegin(); i != children.rend(); i++) (*i)->undo();
    if (pattern) emit project->socket->patternUpdated(pattern.get());
}


