// SPDX-License-Identifier: MIT
//
// Generated by `rlvgl-creator qt emit --target rlvgl` from `tests/fixtures/qt/stopwatch.qml`.
// Do not edit by hand — regenerate with:
//   cargo run --features creator --bin rlvgl-creator -- \
//       qt emit --target rlvgl <input.qml> <out_dir>
//
// Emit-shape contract: docs/qt-support/03b-rlvgl-widget-mapping.md
// QT-03b notes:
//   * helper functions named per §8 (`build_<sanitized_id>` /
//     `build_node_<index>`) so reviewers have stable handles.
//   * bounds resolved per §7 trivial path; non-`fill`/`margins`
//     anchors are deferred to QT-03c.
//   * property lowering per §6; unsupported lower to TODOs.
// QT-04b notes (docs/qt-support/04b-properties-bindings.md):
//   * `pub struct ScreenState` carries every QML root-level
//     property declaration (see §3 / §5).
//   * `build_screen` returns `(WidgetNode, Rc<RefCell<ScreenState>>)`
//     and threads `state` through every helper.
//   * Handler bodies that match the §7 grammar lower to
//     `state.borrow_mut()...` mutations under a `// QT-04b body:`
//     marker; non-matching bodies fall through to `// QT-04 body:`.

#![allow(dead_code)]
#![allow(unused_imports)]
#![allow(unused_variables)]

extern crate alloc;

use alloc::rc::Rc;
use alloc::string::String;
use alloc::vec::Vec;
use core::cell::RefCell;

use rlvgl_core::WidgetNode;
use rlvgl_core::widget::{Color, Rect, Widget};
use rlvgl_widgets::button::Button;
use rlvgl_widgets::click_area::ClickArea;
use rlvgl_widgets::container::Container;
use rlvgl_widgets::label::Label;
use stopwatch_gen::{DataModel, Event, Machine};

/// rlvgl-target emit-shape version. Bumping is Specification-Required
/// (see `docs/qt-support/04b-properties-bindings.md` §11).
pub const QT_EMIT_VERSION: u32 = 13;

/// `qt-ir` schema version this module was generated from.
pub const QT_IR_VERSION: u32 = 2;

/// Source `.qml` file path as recorded at emit time.
pub const QT_SOURCE: &str = "tests/fixtures/qt/stopwatch.qml";

/// QT-05 §6 linkage version. v1 pins the istate Rust
/// template's std-profile shape (VecDeque + Box<dyn Externals>).
pub const ISTATE_LINKAGE_VERSION: u32 = 1;

/// QT-05a §8 derived state-machine ID; matches the
/// `<sm>_gen` crate name stem.
pub const QT_SM_NAME: &str = "stopwatch";

/// State threaded through every helper. One field per
/// QT-04b §5-supported property declared on the QML root.
/// `#[rustfmt::skip]` so the field order matches QT-01a's IR
/// declaration order rather than rustfmt's alphabetical sort.
#[rustfmt::skip]
#[derive(Debug, Clone)]
pub struct ScreenState {
    pub title: String,
}

/// Reactive Label-text binding emitted by QT-04e §3. Each
/// entry pairs a concrete `Rc<RefCell<Label>>` with an
/// accessor that reads the bound state field. Use
/// [`refresh_bindings`] to re-apply every binding in one call.
pub struct LabelBinding {
    pub label: Rc<RefCell<Label>>,
    pub accessor: fn(&ScreenState) -> String,
}

impl LabelBinding {
    /// Re-apply this binding from the supplied state.
    pub fn refresh(&self, state: &ScreenState) {
        self.label.borrow_mut().set_text((self.accessor)(state));
    }
}

/// QT-05c §3 — reactive Label-text binding sourced from the
/// state-machine `DataModel`. Mirrors `LabelBinding` with
/// `&DataModel` instead of `&ScreenState` as the accessor input.
pub struct MachineBinding {
    pub label: Rc<RefCell<Label>>,
    pub accessor: fn(&DataModel) -> String,
}

impl MachineBinding {
    /// Re-apply this binding from the supplied DataModel.
    pub fn refresh(&self, dm: &DataModel) {
        self.label.borrow_mut().set_text((self.accessor)(dm));
    }
}

/// QT-05c §3 — sealed enum over the binding sources reactive
/// `refresh_bindings` knows how to drive. `Label` reads from
/// `ScreenState`; `Machine` reads from `<sm>_gen::DataModel`.
pub enum Binding {
    Label(LabelBinding),
    Machine(MachineBinding),
}

/// Build the screen widget tree at `bounds` and return it
/// alongside the `ScreenState` handle (QT-04b §3), the
/// `Rc<RefCell<Machine>>` istate-codegen handle (QT-05b §3),
/// and the `Vec<Binding>` of reactive bindings (QT-04e §3,
/// QT-05c §3). Callers may dispatch external events via
/// `machine.borrow_mut().dispatch(Event::…)` — the QML-side
/// `dispatch("…")` handlers route through this same machine.
#[rustfmt::skip]
pub fn build_screen(
    bounds: Rect,
) -> (WidgetNode, Rc<RefCell<ScreenState>>, Rc<RefCell<Machine>>, Vec<Binding>) {
    let state = Rc::new(RefCell::new(ScreenState {
        title: String::from("Stopwatch"),
    }));
    let machine = Rc::new(RefCell::new(Machine::new()));
    let mut bindings: Vec<Binding> = Vec::new();
    let node = build_root(bounds, Rc::clone(&state), Rc::clone(&machine), &mut bindings);
    (node, state, machine, bindings)
}

/// Re-apply every QT-04e / QT-05c binding from the current
/// state and machine. Idempotent; safe to call after any
/// mutation. No-op when `bindings` is empty.
#[rustfmt::skip]
pub fn refresh_bindings(state: &Rc<RefCell<ScreenState>>, machine: &Rc<RefCell<Machine>>, bindings: &[Binding]) {
    let s = state.borrow();
    let m = machine.borrow();
    for b in bindings {
        match b {
            Binding::Label(lb) => lb.refresh(&s),
            Binding::Machine(mb) => mb.refresh(&m.dm),
        }
    }
}

/// QT-05c §6: f64::to_string accessor for the bound DM field.
#[inline]
fn format_dm_elapsed(dm: &DataModel) -> String {
    use alloc::string::ToString;
    dm.elapsed.to_string()
}

// QML type: `Item` (id: `root`)
#[rustfmt::skip]
fn build_root(
    bounds: Rect,
    state: Rc<RefCell<ScreenState>>,
    machine: Rc<RefCell<Machine>>,
    bindings: &mut Vec<Binding>,
) -> WidgetNode {
    let widget: Rc<RefCell<dyn Widget>> =
        Rc::new(RefCell::new(Container::new(bounds)));
    let mut node = WidgetNode {
        widget,
        children: Vec::new(),
        tag: Some("root"),
    };
    let child_bounds = Rect {
        x: bounds.x + 0,
        y: bounds.y + 0,
        width: 320,
        height: 60,
    };
    node.children.push(build_display(child_bounds, Rc::clone(&state), Rc::clone(&machine), bindings));
    let child_bounds = Rect {
        x: bounds.x + 0,
        y: bounds.y + 60,
        width: 320,
        height: 30,
    };
    node.children.push(build_counter(child_bounds, Rc::clone(&state), Rc::clone(&machine), bindings));
    let child_bounds = Rect {
        x: bounds.x + 0,
        y: bounds.y + 100,
        width: 100,
        height: 60,
    };
    node.children.push(build_startBtn(child_bounds, Rc::clone(&state), Rc::clone(&machine), bindings));
    let child_bounds = Rect {
        x: bounds.x + 110,
        y: bounds.y + 100,
        width: 100,
        height: 60,
    };
    node.children.push(build_stopBtn(child_bounds, Rc::clone(&state), Rc::clone(&machine), bindings));
    let child_bounds = Rect {
        x: bounds.x + 220,
        y: bounds.y + 100,
        width: 100,
        height: 60,
    };
    node.children.push(build_resetBtn(child_bounds, Rc::clone(&state), Rc::clone(&machine), bindings));
    node
}

// QML type: `Label` (id: `display`)
#[rustfmt::skip]
fn build_display(
    bounds: Rect,
    state: Rc<RefCell<ScreenState>>,
    machine: Rc<RefCell<Machine>>,
    bindings: &mut Vec<Binding>,
) -> WidgetNode {
    // QT-04c bound: text → state.title
    let label_handle: Rc<RefCell<Label>> = Rc::new(RefCell::new(
        Label::new(state.borrow().title.clone(), bounds),
    ));
    let widget: Rc<RefCell<dyn Widget>> = label_handle.clone();
    // QT-04e bound: refresh state.title → label.set_text
    bindings.push(Binding::Label(LabelBinding {
        label: Rc::clone(&label_handle),
        accessor: |s| s.title.clone(),
    }));
    let node = WidgetNode {
        widget,
        children: Vec::new(),
        tag: Some("display"),
    };
    node
}

// QML type: `Label` (id: `counter`)
#[rustfmt::skip]
fn build_counter(
    bounds: Rect,
    state: Rc<RefCell<ScreenState>>,
    machine: Rc<RefCell<Machine>>,
    bindings: &mut Vec<Binding>,
) -> WidgetNode {
    // QT-05c machine-bound: text → sm.dm.elapsed
    let label_handle: Rc<RefCell<Label>> = Rc::new(RefCell::new(
        Label::new(
            { let m = machine.borrow(); format_dm_elapsed(&m.dm) },
        bounds,
    ),
    ));
    let widget: Rc<RefCell<dyn Widget>> = label_handle.clone();
    bindings.push(Binding::Machine(MachineBinding {
        label: Rc::clone(&label_handle),
        accessor: format_dm_elapsed,
    }));
    let node = WidgetNode {
        widget,
        children: Vec::new(),
        tag: Some("counter"),
    };
    node
}

// QML type: `Button` (id: `startBtn`)
#[rustfmt::skip]
fn build_startBtn(
    bounds: Rect,
    state: Rc<RefCell<ScreenState>>,
    machine: Rc<RefCell<Machine>>,
    bindings: &mut Vec<Binding>,
) -> WidgetNode {
    let mut button = Button::new("Start", bounds);
    {
        let machine = Rc::clone(&machine);
        button.set_on_click(move |_b| {
            let mut m = machine.borrow_mut();
            // QT-05b dispatch: start → Event::Start
            m.dispatch(Event::Start);
        });
    }
    let widget: Rc<RefCell<dyn Widget>> = Rc::new(RefCell::new(button));
    let node = WidgetNode {
        widget,
        children: Vec::new(),
        tag: Some("startBtn"),
    };
    node
}

// QML type: `Button` (id: `stopBtn`)
#[rustfmt::skip]
fn build_stopBtn(
    bounds: Rect,
    state: Rc<RefCell<ScreenState>>,
    machine: Rc<RefCell<Machine>>,
    bindings: &mut Vec<Binding>,
) -> WidgetNode {
    let mut button = Button::new("Stop", bounds);
    {
        let machine = Rc::clone(&machine);
        button.set_on_click(move |_b| {
            let mut m = machine.borrow_mut();
            // QT-05b dispatch: stop → Event::Stop
            m.dispatch(Event::Stop);
        });
    }
    let widget: Rc<RefCell<dyn Widget>> = Rc::new(RefCell::new(button));
    let node = WidgetNode {
        widget,
        children: Vec::new(),
        tag: Some("stopBtn"),
    };
    node
}

// QML type: `Button` (id: `resetBtn`)
#[rustfmt::skip]
fn build_resetBtn(
    bounds: Rect,
    state: Rc<RefCell<ScreenState>>,
    machine: Rc<RefCell<Machine>>,
    bindings: &mut Vec<Binding>,
) -> WidgetNode {
    let mut button = Button::new("Reset", bounds);
    {
        let machine = Rc::clone(&machine);
        button.set_on_click(move |_b| {
            let mut m = machine.borrow_mut();
            // QT-05b dispatch: reset → Event::Reset
            m.dispatch(Event::Reset);
        });
    }
    let widget: Rc<RefCell<dyn Widget>> = Rc::new(RefCell::new(button));
    let node = WidgetNode {
        widget,
        children: Vec::new(),
        tag: Some("resetBtn"),
    };
    node
}
