// KueSync — ready-made button presets ("a ton of simple options")
// © 2026 Krometis Analytics. All rights reserved.

import { combineRgb } from '@companion-module/base'

const WHITE = combineRgb(255, 255, 255)
const BLACK = combineRgb(0, 0, 0)
const DARK = combineRgb(30, 30, 30)
const GREEN = combineRgb(0, 120, 0)
const RED = combineRgb(150, 30, 30)

// size:'auto' lets Companion scale each button's text to fit the key — so a long device name or a
// two-line label (e.g. "Stage Right · Inactive") shrinks to fit instead of wrapping/clipping. Callers
// that need a fixed size (big arrows, tiny notes) still override via the style arg.
function button(category, text, actionId, options = {}, feedbacks = [], style = {}) {
  return {
    type: 'button',
    category,
    name: text.replace(/\n/g, ' '),
    style: { text, size: '14', color: WHITE, bgcolor: DARK, ...style },
    steps: [{ down: [{ actionId, options }], up: [] }],
    feedbacks,
  }
}

export function getPresets(self) {
  const v = (name) => `$(${self.label}:${name})`
  const presets = {}
  const TRANSPORT = 'KueSync · Transport'
  const CUE = 'KueSync · Cue / Loop'
  const GOTO = 'KueSync · Go to slide'
  const STATUS = 'KueSync · Status'
  const MEDIA = 'KueSync · Media'
  const MONITOR = 'KueSync · Monitor'

  // ---- transport (all machines) ----
  // DEFAULT NEXT/PREV play in-slide builds & animations, synced across the fleet by timing.
  presets.prev = button(TRANSPORT, 'PREV', 'prev', { mode: 'relative' })
  presets.next = button(TRANSPORT, 'NEXT', 'next', { mode: 'relative' }, [{ feedbackId: 'playing', options: {} }])
  // STATIC variants — absolute slide, self-correcting, for build-free decks / video walls (skip builds).
  presets.prev_static = button(TRANSPORT, 'PREV\nSTATIC', 'prev', { mode: 'synced' })
  presets.next_static = button(TRANSPORT, 'NEXT\nSTATIC', 'next', { mode: 'synced' })
  presets.first = button(TRANSPORT, 'FIRST', 'first')
  presets.last = button(TRANSPORT, 'LAST', 'last')
  presets.start = button(TRANSPORT, 'START', 'start')
  presets.stop = button(TRANSPORT, 'STOP', 'stop')
  presets.jump_fwd = button(TRANSPORT, '+5', 'jump', { dir: 'forward', count: 5 })
  presets.jump_back = button(TRANSPORT, '-5', 'jump', { dir: 'back', count: 5 })
  presets.sync_now = button(TRANSPORT, 'SYNC\nNOW', 'sync_now', {}, [], { bgcolor: GREEN })
  presets.resync = button(TRANSPORT, 'RESYNC\nALL', 'resync', { slide: '' }, [], { bgcolor: GREEN })

  // ---- followers: activate / deactivate (0.9.6 / 0.9.8 auto-populated) ----
  // A TOGGLE button per machine that both parks/un-parks the follower AND shows its state — green Active /
  // red Inactive. These now AUTO-POPULATE from the machines this connection is talking to: each is keyed by
  // the machine's IP and labelled with its DEVICE NAME (matching the leader's labeling), so a button always
  // hits the right physical machine regardless of IP-box order. Re-published when the fleet / a name changes.
  const FOLLOWERS = 'KueSync · Followers'
  const targets = self.targets || []
  targets.forEach((t, i) => {
    const host = String(t.baseHost || t.host)
    const nm = (t.state && t.state.label) ? t.state.label : `Machine ${i + 1}`
    presets[`follower_toggle_${i + 1}`] = button(
      FOLLOWERS, `${nm}\n${v('active_m' + (i + 1))}`, 'follower_toggle_active',
      { machine: host, resync: true },
      [{ feedbackId: 'follower_active', options: { machine: host, activeColor: combineRgb(0, 120, 0), inactiveColor: combineRgb(150, 30, 30) } }])
  })
  // Generic numbered fallbacks (work even before machines connect) + dedicated Activate / Deactivate examples.
  for (let m = 1; m <= 4; m++) {
    presets[`follower_toggle_num_m${m}`] = button(
      FOLLOWERS, `FOLL ${m}\n${v('active_m' + m)}`, 'follower_toggle_active',
      { machine: String(m), resync: true },
      [{ feedbackId: 'follower_active', options: { machine: String(m) } }])
  }
  presets.follower_activate_m1 = button(FOLLOWERS, 'ARM\nFOLL 1', 'follower_activate', { machine: '1', resync: true },
    [{ feedbackId: 'follower_active', options: { machine: '1' } }])
  presets.follower_deactivate_m1 = button(FOLLOWERS, 'PARK\nFOLL 1', 'follower_deactivate', { machine: '1' },
    [{ feedbackId: 'follower_active', options: { machine: '1' } }])

  // ---- launch numbered shows (0.10.0) — auto-populated from KueSync Link, one button per numbered deck ----
  // A press opens that deck on every machine at slide 1 (edit the button's "Machines" to target a subset).
  const LAUNCH = 'KueSync · Launch'
  ;(self.allShows ? self.allShows() : []).forEach((s) => {
    presets[`launch_${s.num}`] = button(LAUNCH, `LAUNCH\n${s.n}${s.title ? '\n' + String(s.title).slice(0, 10) : ''}`, 'launch_show', { show: String(s.num), machines: '' })
  })
  // A generic, editable example (works even before any numbered decks exist — set the number + machines).
  presets.launch_example = button(LAUNCH, 'LAUNCH\nSHOW#', 'launch_show', { show: '', machines: '' })

  // ---- deck control / cue / loop ----
  // GO DECK = arm: bring the show up FULL SCREEN at slide 1 on every machine and HOLD (no advance).
  presets.go_deck = button(CUE, 'GO\nDECK', 'go_deck', {},
    [{ feedbackId: 'playing', options: {} }])
  // (GO LIVE preset removed in 6.2.5 — it was GO DECK + SYNC ROLL fused into one press, which read
  // as redundant/confusing next to SYNC ROLL. The run_cue action it used is unchanged, so any
  // existing GO LIVE buttons keep working; we just stop offering it.)
  // SYNC ROLL = start the synced roll from the CURRENT slide (use after GO DECK). Continuously
  // advances all machines in lockstep, playing builds & animations; at the end Keynote's own "Loop
  // slideshow" wraps to slide 1 (enable it on the deck). Edit "Seconds per slide" for the interval.
  presets.sync_roll = button(CUE, 'SYNC\nROLL', 'run_cue',
    { defaultDwell: 8, perSlide: '', fromStart: false, loop: true, builds: true },
    [{ feedbackId: 'cue_running', options: {} }])
  // END SHOW = stop the roll AND exit the slideshow on every machine (take the fleet down).
  presets.end_show = button(CUE, 'END\nSHOW', 'end_show', {}, [], { bgcolor: RED })
  presets.run_cue = button(CUE, 'RUN\nCUE', 'run_cue',
    { defaultDwell: 8, perSlide: '', fromStart: false, loop: false, builds: true },
    [{ feedbackId: 'cue_running', options: {} }])
  // STATIC variants — absolute per-slide cue sheet (e.g. hold slide 7 for a 120s video), self-correcting,
  // SKIPS in-slide builds. Use on build-free decks / video walls where exact per-slide dwell matters.
  presets.sync_roll_static = button(CUE, 'SYNC\nROLL\nSTATIC', 'run_cue',
    { defaultDwell: 10, perSlide: '', fromStart: true, loop: true, builds: false },
    [{ feedbackId: 'cue_running', options: {} }])
  presets.run_cue_static = button(CUE, 'RUN\nCUE\nSTATIC', 'run_cue',
    { defaultDwell: 10, perSlide: '7=120', fromStart: false, loop: false, builds: false },
    [{ feedbackId: 'cue_running', options: {} }])
  // Panic stop: disengage ANY auto-advance (GO / LOOP / RUN, builds or static) and HOLD on the
  // current slide/build — sends no slide command, so nothing jumps. Always solid red so it's
  // unmistakable on the page.
  presets.stop_auto = button(CUE, 'STOP\nAUTO', 'cancel_cue', {}, [], { bgcolor: RED })
  presets.pause_cue = button(CUE, 'PAUSE\nCUE', 'pause_cue')
  presets.resume_cue = button(CUE, 'RESUME\nCUE', 'resume_cue')
  presets.cancel_cue = button(CUE, 'CANCEL\nCUE', 'cancel_cue')

  // ---- "Go to any slide" — editable: drop it on a button and set the slide number to anything ----
  presets.goto_any = button(GOTO, 'GOTO\nSLIDE#', 'goto', { slide: '1' })
  // ---- quick one-touch buttons for slides 1..40 (highlight the active slide) ----
  for (let n = 1; n <= 40; n++) {
    presets[`goto_${n}`] = button(GOTO, `${n}`, 'goto', { slide: String(n) },
      [{ feedbackId: 'on_slide', options: { slide: n } }])
  }

  // ---- status ----
  // Slide readout — counts EXCLUDE hidden/skipped slides (use current_slide / total_slides for the
  // real Keynote numbers).
  presets.status_slide = {
    type: 'button', category: STATUS, name: 'Current slide (excl. hidden)',
    style: { text: `${v('slide_top')}\n${v('slide_bot')}`, size: 'auto', color: WHITE, bgcolor: BLACK },
    steps: [{ down: [], up: [] }], feedbacks: [{ feedbackId: 'connected', options: {} }],
  }
  // Machines HEALTHY (reporting, not just socket-open) / configured. Green only when all healthy.
  presets.status_agents = {
    type: 'button', category: STATUS, name: 'Machines healthy',
    style: { text: `Healthy\n${v('healthy_count')}/${v('target_count')}`, size: 'auto', color: WHITE, bgcolor: BLACK },
    steps: [{ down: [], up: [] }], feedbacks: [{ feedbackId: 'all_healthy', options: {} }],
  }
  // Live confidence indicator: green when every healthy machine is on the same slide, RED the
  // moment any one slips. Press it to RESYNC ALL (snap the fleet back to the primary's slide).
  presets.status_fleet = {
    type: 'button', category: STATUS, name: 'Fleet in sync',
    style: { text: `FLEET\n${v('fleet_phase')}`, size: 'auto', color: WHITE, bgcolor: GREEN },
    steps: [{ down: [{ actionId: 'resync', options: { slide: '' } }], up: [] }],
    feedbacks: [{ feedbackId: 'fleet_in_sync', options: {} }],
  }
  // Per-machine slide readout (which one drifted, at a glance): e.g. 5·5·4  (✕ = unhealthy).
  presets.status_fleet_slides = {
    type: 'button', category: STATUS, name: 'Per-machine slides',
    style: { text: `${v('fleet_slides')}`, size: '18', color: WHITE, bgcolor: BLACK },
    steps: [{ down: [{ actionId: 'resync', options: { slide: '' } }], up: [] }],
    feedbacks: [{ feedbackId: 'fleet_in_sync', options: {} }],
  }
  // Current Leader (v6 Leader/Follower): who is driving the fleet, by machine number AND IP.
  // Green when that Leader is healthy, amber if it's reported but stale (mid-failover), neutral when
  // there's no Leader (Companion-only operation). Reads "M2 · 192.168.1.51" / "— none —".
  presets.status_leader = {
    type: 'button', category: STATUS, name: 'Current Leader (machine + IP)',
    style: { text: `LEADER\n${v('leader_label')}`, size: 'auto', color: WHITE, bgcolor: BLACK },
    steps: [{ down: [], up: [] }],
    feedbacks: [{ feedbackId: 'leader_known', options: {} }],
  }
  // Shows the status (trial / licensed) AND which machine is providing the authorization (Companion,
  // or the leader agent IP that holds the key).
  // Build position on the current slide (PowerPoint reports it; shows — for Keynote/Mac or no builds).
  // Greens with 'playing'; the FLEET button already turns red on build-level drift across the fleet.
  presets.status_build = {
    type: 'button', category: STATUS, name: 'Build position (PowerPoint)',
    style: { text: `BUILD\n${v('build_readout')}`, size: '18', color: WHITE, bgcolor: BLACK },
    steps: [{ down: [], up: [] }], feedbacks: [{ feedbackId: 'playing', options: {} }],
  }
  presets.status_license = {
    type: 'button', category: STATUS, name: 'License (status + provider)',
    style: { text: `${v('license_state')}\n${v('license_provider')}`, size: 'auto', color: WHITE, bgcolor: BLACK },
    steps: [{ down: [{ actionId: 'revalidate', options: {} }], up: [] }],
    feedbacks: [{ feedbackId: 'license_state', options: {} }],
  }

  // ---- media transport (PowerPoint) ----
  presets.media_play = button(MEDIA, 'PLAY /\nPAUSE', 'media_playpause', { machines: '' }, [{ feedbackId: 'playing', options: {} }])
  presets.media_end = button(MEDIA, 'VIDEO\nEND', 'media_end', { machines: '' })
  presets.media_stop = button(MEDIA, 'VIDEO\nSTOP', 'media_stop', { machines: '' }, [], { bgcolor: RED })

  // ---- video time: TRT / remaining / elapsed (v6.0.8) ----
  // Display buttons (no action). size 'auto' so the time value always fits (even "1:02:33"); short
  // labels so they don't wrap. "Remaining" + the combined button turn amber then red near the end.
  presets.media_remaining = {
    type: 'button', category: MEDIA, name: 'Video — time remaining',
    style: { text: `LEFT\n${v('media_remaining')}`, size: 'auto', color: WHITE, bgcolor: BLACK },
    steps: [{ down: [], up: [] }], feedbacks: [{ feedbackId: 'media_ending', options: { amberAt: 30, redAt: 10 } }],
  }
  presets.media_trt = {
    type: 'button', category: MEDIA, name: 'Video — total running time (TRT)',
    style: { text: `TRT\n${v('media_trt')}`, size: 'auto', color: WHITE, bgcolor: BLACK },
    steps: [{ down: [], up: [] }], feedbacks: [],
  }
  presets.media_elapsed = {
    type: 'button', category: MEDIA, name: 'Video — elapsed',
    style: { text: `ELAPS\n${v('media_elapsed')}`, size: 'auto', color: WHITE, bgcolor: BLACK },
    steps: [{ down: [], up: [] }], feedbacks: [],
  }
  presets.media_time = {
    type: 'button', category: MEDIA, name: 'Video — remaining / TRT (combined)',
    style: { text: `${v('media_remaining')}\nof ${v('media_trt')}`, size: 'auto', color: WHITE, bgcolor: BLACK },
    steps: [{ down: [], up: [] }], feedbacks: [{ feedbackId: 'media_ending', options: { amberAt: 30, redAt: 10 } }],
  }
  presets.media_source = {
    type: 'button', category: MEDIA, name: 'Video — time source (measured / planned)',
    style: { text: `SOURCE\n${v('media_source_short')}`, size: '14', color: WHITE, bgcolor: BLACK },
    steps: [{ down: [], up: [] }], feedbacks: [],
  }
  presets.open_file = button(MEDIA, 'OPEN\nFILE', 'open_file', { path: '', machines: '' })

  // ---- live monitoring (OSCPoint-parity feedback) ----
  presets.monitor_notes = {
    type: 'button', category: MONITOR, name: 'Presenter notes (current slide)',
    style: { text: `${v('slide_notes')}`, size: '7', color: WHITE, bgcolor: BLACK, alignment: 'left:top' },
    steps: [{ down: [], up: [] }], feedbacks: [],
  }
  presets.monitor_presentation = {
    type: 'button', category: MONITOR, name: 'Presentation name',
    style: { text: `${v('presentation_name')}`, size: 'auto', color: WHITE, bgcolor: BLACK },
    steps: [{ down: [], up: [] }], feedbacks: [{ feedbackId: 'connected', options: {} }],
  }
  presets.monitor_slide_name = {
    type: 'button', category: MONITOR, name: 'Slide name / title',
    style: { text: `${v('slide_name')}`, size: 'auto', color: WHITE, bgcolor: BLACK },
    steps: [{ down: [], up: [] }], feedbacks: [],
  }

  // ---- cue light (hardware-style; output-only colored lamps) ----
  // Drop one of these on a key, or tile many to build a big cue light. They light from the fleet's
  // moves — green on forward, red on back — no press behaviour. Build a two-zone DSAN-style panel with
  // GO lamps on some keys and BACK lamps on others.
  const CUELIGHT = 'KueSync · Cue Light'
  // 0.12.2: BOOLEAN lamp feedbacks (lamp_go / lamp_back), rendered by core Companion so they survive an app
  // restart. Each preset carries an EXPLICIT style so the colour applies the instant the feedback goes true
  // (no reliance on defaultStyle). DELETE old cue-light buttons and drag these fresh to move onto the new path.
  const IDLE = combineRgb(14, 20, 25)
  const GO = combineRgb(47, 180, 107)
  const BK = combineRgb(229, 72, 77)
  presets.cue_lamp = {
    type: 'button', category: CUELIGHT, name: 'Cue lamp (green forward / red back) — tileable',
    style: { text: '', size: '14', color: WHITE, bgcolor: IDLE },
    steps: [{ down: [], up: [] }],
    feedbacks: [{ feedbackId: 'lamp_go', options: {}, style: { bgcolor: GO, color: WHITE } }, { feedbackId: 'lamp_back', options: {}, style: { bgcolor: BK, color: WHITE } }],
  }
  presets.cue_back = {
    type: 'button', category: CUELIGHT, name: 'BACK lamp (red on reverse only)',
    style: { text: '<', size: '30', color: WHITE, bgcolor: IDLE },
    steps: [{ down: [], up: [] }],
    feedbacks: [{ feedbackId: 'lamp_back', options: {}, style: { bgcolor: BK, color: WHITE } }],
  }
  presets.cue_go = {
    type: 'button', category: CUELIGHT, name: 'Forward lamp — flashes GREEN on a forward move',
    style: { text: '>', size: '30', color: WHITE, bgcolor: IDLE },
    steps: [{ down: [], up: [] }],
    feedbacks: [{ feedbackId: 'lamp_go', options: {}, style: { bgcolor: GO, color: WHITE } }],
  }

  // ---- KueSync Timer (show timer) ----
  const KUETIMER = 'KueSync · Timer'
  const ktFb = [{ feedbackId: 'kuetimer', options: {} }]
  // Live timer display button: big M:SS that colours itself green/amber/red. Tap = Start/Pause.
  presets.kuetimer_display = {
    type: 'button', category: KUETIMER, name: 'KueSync Timer — live display (tap = start/pause)',
    style: { text: v('kuetimer_time'), size: '24', color: WHITE, bgcolor: BLACK },
    steps: [{ down: [{ actionId: 'kuetimer_toggle', options: {} }], up: [] }],
    feedbacks: ktFb,
  }
  presets.kuetimer_5 = button(KUETIMER, 'START\n5:00', 'kuetimer_start', { minutes: 5, seconds: 0, warn: 60, end: 'blink' }, ktFb)
  presets.kuetimer_10 = button(KUETIMER, 'START\n10:00', 'kuetimer_start', { minutes: 10, seconds: 0, warn: 120, end: 'blink' }, ktFb)
  presets.kuetimer_20 = button(KUETIMER, 'START\n20:00', 'kuetimer_start', { minutes: 20, seconds: 0, warn: 120, end: 'blink' }, ktFb)
  presets.kuetimer_toggle = button(KUETIMER, 'START /\nPAUSE', 'kuetimer_toggle', {}, ktFb)
  presets.kuetimer_plus = button(KUETIMER, '+1:00', 'kuetimer_adjust', { delta: 60 })
  presets.kuetimer_minus = button(KUETIMER, '-1:00', 'kuetimer_adjust', { delta: -60 })
  presets.kuetimer_reset = button(KUETIMER, 'RESET', 'kuetimer_reset', {})
  presets.kuetimer_zero = button(KUETIMER, 'TO\nZERO', 'kuetimer_zero', {})
  presets.kuetimer_countup = button(KUETIMER, 'COUNT\nUP', 'kuetimer_countup', {}, ktFb)
  presets.kuetimer_tod = button(KUETIMER, 'TIME\nOF DAY', 'kuetimer_tod', {}, ktFb)

  return presets
}
