#include "pch.h"

#include "legacy_document_animation_services.h"

#include "app.h"
#include "canvas.h"
#include "node_panel_animation.h"

namespace pp::panopainter {

class LegacyDocumentAnimationServices final : public pp::app::DocumentAnimationServices {
public:
    LegacyDocumentAnimationServices(NodePanelAnimation& panel, Layer* layer) noexcept
        : panel_(panel)
        , layer_(layer)
    {
    }

    void add_frame() override
    {
        Canvas::I->layer().add_frame();
    }

    void duplicate_frame(int selected_frame) override
    {
        if (layer_)
            layer_->duplicate_frame(selected_frame);
    }

    void remove_frame(int selected_frame, int target_frame) override
    {
        if (!layer_)
            return;
        layer_->remove_frame(selected_frame);
        panel_.m_selected_frame_index = target_frame;
    }

    void set_frame_duration(int selected_frame, int duration) override
    {
        if (layer_)
            layer_->set_frame_duration(selected_frame, duration);
    }

    int move_frame(int selected_frame, int move_offset) override
    {
        if (!layer_)
            return selected_frame;
        panel_.m_selected_frame_index = layer_->move_frame_offset(selected_frame, move_offset);
        return panel_.m_selected_frame_index;
    }

    void select_frame(std::uint32_t layer_id, int layer_index, int selected_frame) override
    {
        panel_.m_selected_frame_layer_id = layer_id;
        panel_.m_selected_frame_index = selected_frame;
        panel_.m_timeline->m_frame = selected_frame;
    }

    void select_layer(int layer_index) override
    {
        App::I->layers->handle_layer_selected(App::I->layers->get_layer_at(layer_index));
    }

    void goto_frame(int target_frame) override
    {
        Canvas::I->anim_goto_frame(target_frame);
    }

    void set_timeline_frame(int target_frame) override
    {
        panel_.m_timeline->m_frame = target_frame;
    }

    void set_onion_size(int onion_size) override
    {
        panel_.m_timeline->m_onion_size = onion_size;
    }

    void capture_playback_restore_mode() override
    {
        playback_restore_mode() = Canvas::I->m_current_mode;
    }

    void enter_playback_camera_mode() override
    {
        Canvas::set_mode(kCanvasMode::Camera);
    }

    void restore_playback_canvas_mode() override
    {
        Canvas::set_mode(playback_restore_mode());
    }

    void set_playback_active(bool active) override
    {
        panel_.btn_play->set_active(active);
    }

    void reset_playback_timer() override
    {
        panel_.m_playback_timer = 0;
    }

    void set_playback_idle_ms(int idle_ms) override
    {
        App::I->idle_ms = idle_ms;
    }

    void update_canvas_animation() override
    {
        Canvas::I->anim_update();
    }

    void update_frame_status() override
    {
        panel_.update_frames();
    }

    void reload_animation_layers() override
    {
        panel_.load_layers();
    }

    void mark_unsaved() override
    {
        Canvas::I->m_unsaved = true;
    }

private:
    static kCanvasMode& playback_restore_mode()
    {
        static auto mode = Canvas::I->m_current_mode;
        return mode;
    }

    NodePanelAnimation& panel_;
    Layer* layer_ = nullptr;
};

pp::foundation::Status execute_legacy_document_animation_plan(
    NodePanelAnimation& panel,
    const pp::app::DocumentAnimationOperationPlan& plan,
    Layer* layer)
{
    LegacyDocumentAnimationServices services(panel, layer);
    return pp::app::execute_animation_operation_plan(plan, services);
}

} // namespace pp::panopainter
