#include "project.h"
using Xybrid::Data::Project;
using Xybrid::Data::Pattern;

#include "data/graph.h"
using Xybrid::Data::Graph;

#include "audio/audioengine.h"
using namespace Xybrid::Audio;

Project::Project() {
    rootGraph = std::make_shared<Graph>();
    rootGraph->project = this;
}

Project::~Project() {
    // orphan patterns so they're not pointing at a non-project
    for (auto& pat : patterns) pat->project = nullptr;
}

bool Project::editingLocked() {
    return (audioEngine->playingProject().get() == this && (audioEngine->playbackMode() == AudioEngine::Playing || audioEngine->playbackMode() == AudioEngine::Paused));
}

void Project::updatePatternIndices() {
    for (size_t i = 0; i < patterns.size(); i++) patterns[i]->index = i;
}

std::shared_ptr<Pattern> Project::newPattern(size_t idx) {
    auto pt = std::make_shared<Pattern>(time.rowsPerMeasure() * 4);
    pt->time = time;
    pt->project = this;
    if (idx >= patterns.size()) {
        pt->index = patterns.size();
        patterns.push_back(pt);
    } else {
        patterns.insert(patterns.begin() + static_cast<ptrdiff_t>(idx), pt);
        updatePatternIndices();
    }
    return pt;
}

void Project::removePattern(Pattern* p) {
    if (!p || p->project != this || p->index >= patterns.size() || patterns[p->index].get() != p) return;
    // remove from sequence first
    sequence.erase(std::remove(sequence.begin(), sequence.end(), p), sequence.end());
    // remove from pattern list and adjust numbers
    patterns.erase(patterns.begin() + static_cast<ptrdiff_t>(p->index));
    updatePatternIndices();
    // finally, explicitly orphan
    p->project = nullptr;
}
