// Copyright 2026 Ling71671
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

///|
pub struct GalleryState {
  mut button_clicks : Int
  mut checkbox_gpu : Bool
  mut checkbox_grid : Bool
  mut checkbox_dark_contrast : Bool
  mut checkbox_antialiasing : Bool
  mut toggle_minimal : Bool
  mut toggle_autosave : Bool
  mut toggle_retina : Bool
  mut toggle_haptics : Bool
  mut radio_quality : Int
  mut slider_zoom : Double
  mut slider_opacity : Double
  mut drag_x : Double
  mut drag_y : Double
  mut drag_scale : Double
  mut stepper_count : Double
  mut stepper_gain : Double
  mut rating_val : Double
  mut steps_current : Int
  mut pagination_page : Int
  mut knob_cutoff : Double
  mut knob_res : Double
  mut knob_pan : Double
  mut knob_drive : Double
  mut fader_vol : Double
  mut fader_gain : Double
  mut fader_l : Double
  mut fader_r : Double
  mut combo_format : Int
  mut combo_color : Int
  mut color_idx : Int
  mut progress_val : Double
  mut tree_selected : String?
  mut tree_expanded : Array[String]
  mut tab_selected : Int
  mut text_name : String
  mut text_email : String
  mut code_buffer : String
  toasts : Array[@widgets.Toast]
  mut cmd_open : Bool
  mut cmd_query : String
  mut cmd_idx : Int
  mut ctx_menu_open : Bool
  mut ctx_menu_pos : @math.Vec2
  mut status_text : String
  mut active_comp_id : String
  mut splitter_ratio : Double
  mut table_sort_col : String
  mut table_sort_dir : @composite.TableSortDirection
  table_columns : Array[@composite.TableColumn]
  mut table_selected_row : Int
  mut dialog_open : Bool
  mut dialog_last_result : String
  mut segmented_sel : Int
  mut tag1_open : Bool
  mut tag2_open : Bool
  mut tag3_open : Bool
  sparkline_data : Array[Double]
  mut color_picker_val : @color.Color
  mut breadcrumb_last_clicked : String
  mut rich_text_last_url : String
  mut dock_tree : @composite.DockTree
  node_items : Array[@composite.NodeItem]
  node_conns : Array[@composite.NodeConnection]
  mut spring_puck_x : Double
  mut spring_puck_y : Double
  spring_model : @math.Spring2D
  mut spring_stiffness : Double
  mut spring_damping : Double
  mut spring_dragging : Bool
  mut svg_export_done : Bool
}

///|
let gallery_state : GalleryState = {
  button_clicks: 0,
  checkbox_gpu: true,
  checkbox_grid: false,
  checkbox_dark_contrast: false,
  checkbox_antialiasing: true,
  toggle_minimal: true,
  toggle_autosave: false,
  toggle_retina: true,
  toggle_haptics: false,
  radio_quality: 1,
  slider_zoom: 1.25,
  slider_opacity: 85.0,
  drag_x: 120.0,
  drag_y: 80.0,
  drag_scale: 1.0,
  stepper_count: 5.0,
  stepper_gain: 0.0,
  rating_val: 4.5,
  steps_current: 1,
  pagination_page: 1,
  knob_cutoff: 1200.0,
  knob_res: 25.0,
  knob_pan: 0.0,
  knob_drive: 6.0,
  fader_vol: 0.75,
  fader_gain: 0.0,
  fader_l: 0.65,
  fader_r: 0.65,
  combo_format: 0,
  combo_color: 1,
  color_idx: 0,
  progress_val: 0.68,
  tree_selected: Some("main_mbt"),
  tree_expanded: ["src", "assets"],
  tab_selected: 0,
  text_name: "MoonBit Developer",
  text_email: "dev@moonbitlang.com",
  code_buffer: "///| Welcome to moon-egui native CodeEditor\npub fn render(ui : @core.UIContext) -> Unit {\n  ui.label(\"Pure MoonBit Wasm Engine!\")\n  @widgets.button(ui, \"Live Immediate-Mode\")\n}",
  toasts: [],
  cmd_open: false,
  cmd_query: "",
  cmd_idx: 0,
  ctx_menu_open: false,
  ctx_menu_pos: @math.Vec2::new(180.0, 140.0),
  status_text: "Ready",
  active_comp_id: "",
  splitter_ratio: 0.45,
  table_sort_col: "id",
  table_sort_dir: @composite.TableSortDirection::Ascending,
  table_columns: [
    @composite.TableColumn::new("id", "ID", 60.0, min_width=50.0),
    @composite.TableColumn::new("name", "Name", 140.0, min_width=80.0),
    @composite.TableColumn::new("role", "Role", 110.0, min_width=70.0),
    @composite.TableColumn::new("score", "Score", 80.0, min_width=60.0),
  ],
  table_selected_row: 1,
  dialog_open: false,
  dialog_last_result: "None",
  segmented_sel: 0,
  tag1_open: true,
  tag2_open: true,
  tag3_open: true,
  sparkline_data: [
    12.0, 28.0, 19.0, 35.0, 22.0, 48.0, 38.0, 55.0, 42.0, 68.0, 60.0, 85.0,
  ],
  color_picker_val: @color.Color::rgb(79, 70, 229),
  breadcrumb_last_clicked: "None",
  rich_text_last_url: "None",
  dock_tree: @composite.DockTree::split(
    @composite.DockSplitDirection::Horizontal,
    0.28,
    @composite.DockTree::leaf([
      @composite.DockTab::new("explorer", "资源管理器"),
      @composite.DockTab::new("outline", "大纲视图"),
    ]),
    @composite.DockTree::split(
      @composite.DockSplitDirection::Vertical,
      0.62,
      @composite.DockTree::leaf([
        @composite.DockTab::new("canvas", "CAD 视口", closable=false),
        @composite.DockTab::new("shader", "着色器源码", closable=true),
      ]),
      @composite.DockTree::leaf([
        @composite.DockTab::new(
          "console",
          "运行日志 (Output)",
          closable=true,
        ),
        @composite.DockTab::new("terminal", "终端 (Terminal)", closable=true),
      ]),
    ),
  ),
  node_items: [
    @composite.NodeItem::new(
      "audio_src",
      "音频源 (Audio Source)",
      @math.Vec2::new(30.0, 40.0),
      outputs=[@composite.NodePort::output("out_wav", "PCM Wave")],
      accent_color=@color.Color::accent_primary(),
    ),
    @composite.NodeItem::new(
      "dsp_filter",
      "低通滤波 (LowPass DSP)",
      @math.Vec2::new(240.0, 40.0),
      inputs=[@composite.NodePort::input("in_audio", "Input")],
      outputs=[@composite.NodePort::output("out_filtered", "Filtered")],
      accent_color=@color.Color::success(),
    ),
    @composite.NodeItem::new(
      "sink_out",
      "扬声器输出 (Audio Sink)",
      @math.Vec2::new(450.0, 70.0),
      inputs=[@composite.NodePort::input("in_sink", "Left / Right")],
      accent_color=@color.Color::warning(),
    ),
  ],
  node_conns: [
    @composite.NodeConnection::new(
      "audio_src", "out_wav", "dsp_filter", "in_audio",
    ),
    @composite.NodeConnection::new(
      "dsp_filter", "out_filtered", "sink_out", "in_sink",
    ),
  ],
  spring_puck_x: 200.0,
  spring_puck_y: 120.0,
  spring_model: @math.Spring2D::new(@math.Vec2::new(200.0, 120.0)),
  spring_stiffness: 180.0,
  spring_damping: 20.0,
  spring_dragging: false,
  svg_export_done: false,
}

///|
let gallery_ctx : @core.UIContext = @core.UIContext::new()

///|
pub fn get_gallery_status() -> String {
  let s = gallery_state.status_text
  if s.is_empty() {
    "Ready"
  } else {
    s
  }
}

///|
pub fn get_gallery_cursor() -> String {
  gallery_ctx.cursor_icon()
}

// ----------------------------------------------------------------------
// Frame Step Dispatcher
// ----------------------------------------------------------------------

///|
fn draw_component_preview(
  ui : @core.UIContext,
  comp_id : String,
  cur_w : Double,
  cur_h : Double,
) -> Unit {
  match comp_id {
    // Basic Input (gallery_basic_stages.mbt & gallery_editor_stages.mbt)
    "button" => draw_button_showcase(ui)
    "text_edit" => draw_text_edit_showcase(ui)
    "code_editor" => draw_code_editor_showcase(ui)

    // Values & Selection (gallery_basic_stages.mbt & gallery_audio_stages.mbt & gallery_container_stages.mbt)
    "checkbox" => draw_checkbox_showcase(ui)
    "toggle" => draw_toggle_showcase(ui)
    "radio" => draw_radio_showcase(ui)
    "slider" => draw_slider_showcase(ui)
    "drag_value" => draw_drag_value_showcase(ui)
    "stepper" => draw_stepper_showcase(ui)
    "rating" => draw_rating_showcase(ui)
    "knob" => draw_knob_showcase(ui)
    "fader" => draw_fader_showcase(ui)
    "combo_box" => draw_combo_box_showcase(ui)
    "color_button" => draw_color_button_showcase(ui)

    // Feedback & Presentation (gallery_basic_stages.mbt & gallery_container_stages.mbt & gallery_data_stages.mbt)
    "progress_bar" => draw_progress_bar_showcase(ui)
    "collapsing_header" => draw_collapsing_header_showcase(ui)
    "tree_view" => draw_tree_view_showcase(ui)
    "tooltip" => draw_tooltip_showcase(ui)

    // Containers & Layout (gallery_nav_stages.mbt & gallery_container_stages.mbt & gallery_data_stages.mbt)
    "tab_bar" => draw_tab_bar_showcase(ui)
    "steps" => draw_steps_showcase(ui)
    "pagination" => draw_pagination_showcase(ui)
    "menu_bar" => draw_menu_bar_showcase(ui)
    "scroll_area" => draw_scroll_area_showcase(ui)
    "window" => draw_window_showcase(ui, cur_w, cur_h)
    "command_palette" => draw_command_palette_showcase(ui)
    "context_menu" => draw_context_menu_showcase(ui, cur_w, cur_h)
    "toast" => draw_toast_showcase(ui, cur_w, cur_h)
    "splitter" => draw_splitter_showcase(ui)
    "dock_area" => draw_dock_area_showcase(ui, cur_w, cur_h)
    "table" => draw_table_showcase(ui)
    "dialog" => draw_dialog_showcase(ui, cur_w, cur_h)
    "spinner" => draw_spinner_showcase(ui)
    "sparkline" => draw_sparkline_showcase(ui)
    "plot" => draw_plot_showcase(ui)
    "bar_chart" => draw_bar_chart_showcase(ui)
    "node_editor" => draw_node_editor_showcase(ui)
    "segmented_control" => draw_segmented_control_showcase(ui)
    "badge" => draw_badge_showcase(ui)
    "breadcrumb" => draw_breadcrumb_showcase(ui)
    "color_picker" => draw_color_picker_showcase(ui)
    "rich_text" => draw_rich_text_showcase(ui)
    "virtual_list" => draw_virtual_list_showcase(ui, cur_w, cur_h)
    "spring_physics" => draw_spring_physics_showcase(ui, cur_w, cur_h)
    "svg_export" => draw_svg_export_showcase(ui)
    _ => {
      let _ = ui.label_colored(
        "MoonBit 原生组件: " + comp_id,
        @color.Color::accent_primary(),
      )
      ui.spacer(10.0)
      draw_button_showcase(ui)
    }
  }
}

///|
/// Native MoonBit Component Showcase Frame Entry Point.
/// Evaluates native widgets and returns pure @draw.DrawList to JavaScript.
pub fn gallery_step(
  comp_id : String,
  mouse_x : Double,
  mouse_y : Double,
  mouse_down : Bool,
  scroll_dy : Double,
  vp_w : Double,
  vp_h : Double,
  text_input : String,
  keys_pressed : Array[String],
  keys_released : Array[String],
  mod_flags : Int,
  mouse_secondary_down? : Bool = false,
) -> @draw.DrawList {
  let cur_w = if vp_w > 100.0 { vp_w } else { 800.0 }
  let cur_h = if vp_h > 100.0 { vp_h } else { 500.0 }

  // 1. Convert host inputs to RawInput
  let raw = host_raw_input(
    mouse_x,
    mouse_y,
    mouse_down,
    text_input,
    keys_pressed,
    keys_released,
    mod_flags,
    scroll_dy~,
    mouse_secondary_down~,
  )

  // 2. Begin Frame
  if comp_id != gallery_state.active_comp_id {
    gallery_state.active_comp_id = comp_id
    gallery_state.cmd_open = false
    gallery_state.ctx_menu_open = false
    gallery_ctx.set_open_combo_id(@core.Id::zero())
    gallery_ctx.set_open_menu_id(@core.Id::zero())
  }
  gallery_ctx.begin_frame(raw)

  // 3. Render Subtle Studio Light Grid Background
  let painter = gallery_ctx.painter()
  painter.add_rect(
    @math.Rect::new(0.0, 0.0, cur_w, cur_h),
    @color.Color::bg_subtle(),
    0.0,
  )

  // 4. Centered White Porcelain Card Container
  let pad_x = if cur_w > 560.0 { 32.0 } else { 12.0 }
  let pad_y = 24.0
  let card_w = cur_w - pad_x * 2.0
  let card_h = cur_h - pad_y * 2.0
  let card_rect = @math.Rect::new(pad_x, pad_y, card_w, card_h)

  // Porcelain Card Disc & Border Shadow
  painter.add_rect(
    @math.Rect::new(pad_x, pad_y + 2.0, card_w, card_h),
    @color.Color::shadow(),
    8.0,
  )
  painter.add_rect(card_rect, @color.Color::bg_window(), 8.0)
  painter.add_rect_stroke(card_rect, @color.Color::border_default(), 1.0, 8.0)

  // Layout Cursor within Porcelain Card
  gallery_ctx.set_cursor(@math.Vec2::new(pad_x + 20.0, pad_y + 18.0))
  gallery_ctx.set_available_width(card_w - 40.0)

  // 5. Component Showcase Dispatcher for ALL components
  draw_component_preview(gallery_ctx, comp_id, card_w, card_h)

  // 6. End Frame & Output DrawList
  gallery_ctx.end_frame()
}