void ScenarioCreate<EventModel>::undo(
    const Id<EventModel>& id,
    ScenarioModel& s)
{
    auto& ev = s.event(id);
    s.timeNode(ev.timeNode()).removeEvent(id);
    s.events.remove(&ev);
}
void ScenarioCreate<StateModel>::undo(
    const Id<StateModel> &id,
    ScenarioModel &s)
{
    auto& state = s.state(id);
    auto& ev = s.event(state.eventId());

    ev.removeState(id);

    s.states.remove(&state);
}
void Visitor<Writer<DataStream>>::writeTo(ScenarioModel& scenario)
{
    scenario.pluginModelList = new iscore::ElementPluginModelList{*this, &scenario};

    m_stream >> scenario.m_startTimeNodeId
             >> scenario.m_endTimeNodeId;
    m_stream >> scenario.m_startEventId
             >> scenario.m_endEventId;

    // Timenodes
    int timenode_count;
    m_stream >> timenode_count;

    for(; timenode_count -- > 0;)
    {
        auto tnmodel = new TimeNodeModel {*this, &scenario};
        scenario.addTimeNode(tnmodel);
    }

    // Events
    int event_count;
    m_stream >> event_count;

    for(; event_count -- > 0;)
    {
        auto evmodel = new EventModel {*this, &scenario};
        scenario.addEvent(evmodel);
    }

    // Events
    int state_count;
    m_stream >> state_count;

    for(; state_count -- > 0;)
    {
        auto stmodel = new StateModel {*this, &scenario};
        scenario.addDisplayedState(stmodel);
    }

    // Constraints
    int constraint_count;
    m_stream >> constraint_count;

    for(; constraint_count -- > 0;)
    {
        auto constraint = new ConstraintModel {*this, &scenario};
        scenario.addConstraint(constraint);
    }

    checkDelimiter();
}
void Visitor<Reader<JSONObject>>::readFrom(const ScenarioModel& scenario)
{
    m_obj["PluginsMetadata"] = toJsonValue(*scenario.pluginModelList);

    m_obj["StartTimeNodeId"] = toJsonValue(scenario.m_startTimeNodeId);
    m_obj["EndTimeNodeId"] = toJsonValue(scenario.m_endTimeNodeId);
    m_obj["StartEventId"] = toJsonValue(scenario.m_startEventId);
    m_obj["EndEventId"] = toJsonValue(scenario.m_endEventId);

    m_obj["TimeNodes"] = toJsonArray(scenario.timeNodes());
    m_obj["Events"] = toJsonArray(scenario.events());
    m_obj["States"] = toJsonArray(scenario.states());
    m_obj["Constraints"] = toJsonArray(scenario.constraints());
}
//TODO unused ?
void ScenarioCreate<ConstraintModel>::undo(
    const id_type<ConstraintModel>& id,
    ScenarioModel& s)
{
    auto& cst = s.constraint(id);

    auto& sev = s.state(cst.startState());
    auto& eev = s.state(cst.endState());

    sev.setNextConstraint(id_type<ConstraintModel> {});
    eev.setPreviousConstraint(id_type<ConstraintModel> {});

    s.removeConstraint(&cst);
}
void Visitor<Reader<DataStream>>::readFrom(const ScenarioModel& scenario)
{
    readFrom(*scenario.pluginModelList);

    m_stream << scenario.m_startTimeNodeId
             << scenario.m_endTimeNodeId;
    m_stream << scenario.m_startEventId
             << scenario.m_endEventId;

    // Timenodes
    const auto& timenodes = scenario.timeNodes();
    m_stream << (int) timenodes.size();

    for(const auto& timenode : timenodes)
    {
        readFrom(*timenode);
    }

    // Events
    const auto& events = scenario.events();
    m_stream << (int) events.size();

    for(const auto& event : events)
    {
        readFrom(*event);
    }

    // States
    const auto& states = scenario.states();
    m_stream << (int) states.size();

    for(const auto& state : states)
    {
        readFrom(*state);
    }

    // Constraints
    const auto& constraints = scenario.constraints();
    m_stream << (int) constraints.size();

    for(const auto& constraint : constraints)
    {
        readFrom(*constraint);
    }



    insertDelimiter();
}
void Visitor<Writer<JSONObject>>::writeTo(ScenarioModel& scenario)
{
    Deserializer<JSONValue> elementPluginDeserializer(m_obj["PluginsMetadata"]);
    scenario.pluginModelList = new iscore::ElementPluginModelList{elementPluginDeserializer, &scenario};

    scenario.m_startTimeNodeId = fromJsonValue<id_type<TimeNodeModel>> (m_obj["StartTimeNodeId"]);
    scenario.m_endTimeNodeId = fromJsonValue<id_type<TimeNodeModel>> (m_obj["EndTimeNodeId"]);
    scenario.m_startEventId = fromJsonValue<id_type<EventModel>> (m_obj["StartEventId"]);
    scenario.m_endEventId = fromJsonValue<id_type<EventModel>> (m_obj["EndEventId"]);

    for(const auto& json_vref : m_obj["TimeNodes"].toArray())
    {
        auto tnmodel = new TimeNodeModel {
                       Deserializer<JSONObject>{json_vref.toObject() },
                       &scenario};

        scenario.addTimeNode(tnmodel);
    }

    for(const auto& json_vref : m_obj["Events"].toArray())
    {
        auto evmodel = new EventModel {
                       Deserializer<JSONObject>{json_vref.toObject() },
                       &scenario};

        scenario.addEvent(evmodel);
    }

    for(const auto& json_vref : m_obj["States"].toArray())
    {
        auto stmodel = new StateModel {
                       Deserializer<JSONObject>{json_vref.toObject() },
                       &scenario};

        scenario.addDisplayedState(stmodel);
    }

    for(const auto& json_vref : m_obj["Constraints"].toArray())
    {
        auto constraint = new ConstraintModel{
                Deserializer<JSONObject>{json_vref.toObject() },
                &scenario};
        scenario.addConstraint(constraint);
    }
}
void ScenarioGlobalCommandManager::removeSelection(const ScenarioModel &scenario)
{
    Selection sel = scenario.selectedChildren();

    // We have to remove the first / last timenodes / events from the selection.
    erase_if(sel, [&] (auto&& elt) {
        return elt == &scenario.startEvent()
            || elt == &scenario.endEvent()
            || elt == &scenario.startTimeNode()
            || elt == &scenario.endTimeNode();
    });

    if(!sel.empty())
    {
        CommandDispatcher<> dispatcher(m_commandStack);
        dispatcher.submitCommand(new RemoveSelection(path(scenario), sel));
    }
}
    void updatePositions(
            ScenarioModel& scenario,
            const QVector<id_type<TimeNodeModel> >& translatedTimeNodes,
            const TimeValue& deltaTime,
            ProcessScaleMethod&& scaleMethod)
    {
        for (const auto& timeNode_id : translatedTimeNodes)
        {
            auto& timeNode = scenario.timeNode(timeNode_id);
            timeNode.setDate(timeNode.date() + deltaTime);
            for (const auto& event : timeNode.events())
            {
                scenario.event(event).setDate(timeNode.date());
            }
        }

        for(const auto& constraint : scenario.constraints())
        {
            const auto& startDate = scenario.event(scenario.state(constraint->startState()).eventId()).date();
            const auto& endDate = scenario.event(scenario.state(constraint->endState()).eventId()).date();

            TimeValue newDuration = endDate - startDate;

            if (!(constraint->startDate() - startDate).isZero())
            {
                constraint->setStartDate(startDate);
            }

            if(!(constraint->defaultDuration() - newDuration).isZero())
            {
                ConstraintModel::Algorithms::setDurationInBounds(*constraint, newDuration);
                for(const auto& process : constraint->processes())
                {
                    scaleMethod(process, newDuration);
                }
            }

            emit scenario.constraintMoved(constraint->id());
        }
    }
void ScenarioCreate<TimeNodeModel>::undo(
    const id_type<TimeNodeModel>& id,
    ScenarioModel& s)
{
    s.removeTimeNode(&s.timeNode(id));
}