// editor_input_deck.cpp — the DECKS band's input: toggles (committed at once, a discrete
// final edit), knob grabs (grab-anchored vertical drag, committed on release), the live
// knob-drag resolution, and the band's hover. Windows-only.

#include "shell/instrument/reasampler_editor.h"

#ifdef _WIN32

#include "core/instrument/ui/knob_deck.h"       // hitTestDeck / layoutDeck
#include "core/instrument/ui/param_slider.h"    // knobDragValue (grab-anchored drag)
#include "shell/instrument/editor_internal.h"
#include "shell/instrument/reasampler_processor.h"

namespace reasampler::vst {

using namespace reasampler::ui;
using namespace reasampler::instrument::ui;

bool ReaSamplerEditor::mouseDownDeck(const FaceLayout& fl, int x, int y) {
    const Rect& band = fl.bands.decks;
    if (!contains(band, x, y)) return false;

    const DeckLayout dl = layoutDeck(fl.deckDescs, band.x, band.y, band.width);
    const DeckHit hit = hitTestDeck(dl, x, y);
    if (hit.kind == DeckHitKind::CaptionToggle || hit.kind == DeckHitKind::RowToggle) {
        switch (static_cast<ParamControl>(hit.id)) {
            case ParamControl::kVoiceMode: {
                // Processor-side per-instance param: live setter (engine rebuild via the
                // drain-slot swap — tails survive), local snapshot in step.
                const VoiceMode m = (hit.segment == 1) ? VoiceMode::Mono : VoiceMode::Poly;
                if (m != voiceMode_) {
                    voiceMode_ = m;
                    processor_->setVoiceMode(m);
                }
                invalidate();
                break;
            }
            case ParamControl::kMonoTrigger: {
                if (voiceMode_ != VoiceMode::Mono) break;  // Disabled (inert) in Poly
                const MonoTrigger t =
                    (hit.segment == 1) ? MonoTrigger::Legato : MonoTrigger::Retrigger;
                if (t != monoTrigger_) {
                    monoTrigger_ = t;
                    processor_->setMonoTrigger(t);
                }
                invalidate();
                break;
            }
            default:
                // Parameter-set toggles (play mode / pitch engine / pitch-env enable).
                applyParamControl(hit.id, 0.0, hit.segment);
                commitAndReload();
                break;
        }
        return true;
    }
    if (hit.kind == DeckHitKind::Knob) {
        // PITCH ENV knobs are Disabled (drawn, inert) while the envelope is off.
        const bool pitchEnvKnob =
            hit.id == static_cast<int>(ParamControl::kPitchEnvAttack) ||
            hit.id == static_cast<int>(ParamControl::kPitchEnvDecay) ||
            hit.id == static_cast<int>(ParamControl::kPitchEnvDepth);
        if (pitchEnvKnob && !params_.play.pitchEnv.enabled) return true;
        drag_ = DragKind::kDeckKnob;
        dragParamId_ = hit.id;
        dragKnobStartValue_ = deckControlNorm(hit.id);
        // Processor-side knobs (voice count / master gain) are transient live writes with no
        // parameter-set mutation, so they need no rollback snapshot.
        dragStartParams_ = params_;
        dragStartX_ = x;
        dragStartY_ = y;
        invalidate();
    }
    // The deck band swallows its own clicks either way — no fall-through to the waveform.
    return true;
}

void ReaSamplerEditor::dragDeck(int x, int y) {
    // Radial knob: grab-anchored vertical drag — knobDragValue maps the y delta from the
    // value at grab (up = increase), so the value tracks relative motion and never jumps on
    // grab. Live feedback; parameter-set commits land on WM_LBUTTONUP.
    (void)x;
    applyDeckKnob(dragParamId_, knobDragValue(dragKnobStartValue_, y - dragStartY_));
    invalidate();
}

ReaSamplerEditor::HoverTarget ReaSamplerEditor::hoverDeck(const FaceLayout& fl, int x,
                                                          int y) const {
    const Rect& band = fl.bands.decks;
    if (!contains(band, x, y)) return {};
    const DeckLayout dl = layoutDeck(fl.deckDescs, band.x, band.y, band.width);
    const DeckHit dh = hitTestDeck(dl, x, y);
    if (dh.kind == DeckHitKind::None) return {};
    return {HoverKind::kControl, dh.id};
}

}  // namespace reasampler::vst

#endif  // _WIN32
