// Package ipc provides Unix socket IPC for remote playback control of cliamp.
// The protocol is newline-delimited JSON over a Unix domain socket.
package ipc

import "time"

// Compile-time interface check.
var _ Dispatcher = DispatcherFunc(nil)

// Request is the JSON command sent by the client.
type Request struct {
	Cmd      string   `json:"cmd"`
	Value    float64  `json:"value,omitempty"`
	Playlist string   `json:"playlist,omitempty"`
	Path     string   `json:"path,omitempty"`
	Name     string   `json:"name,omitempty"`
	Band     int      `json:"band,omitempty"`
	Sub      string   `json:"sub,omitempty"`
	Args     []string `json:"args,omitempty"`
}

// Response is the JSON response sent by the server.
type Response struct {
	OK         bool       `json:"ok"`
	Error      string     `json:"error,omitempty"`
	State      string     `json:"state,omitempty"`
	Track      *TrackInfo `json:"track,omitempty"`
	Position   float64    `json:"position,omitempty"`
	Duration   float64    `json:"duration,omitempty"`
	Volume     float64    `json:"volume,omitempty"`
	Playlist   string     `json:"playlist,omitempty"`
	Index      int        `json:"index,omitempty"`
	Total      int        `json:"total,omitempty"`
	Visualizer string     `json:"visualizer,omitempty"`
	Shuffle    *bool      `json:"shuffle,omitempty"`
	Repeat     string     `json:"repeat,omitempty"`
	Mono       *bool      `json:"mono,omitempty"`
	Speed      float64    `json:"speed,omitempty"`
	EQPreset   string     `json:"eq_preset,omitempty"`
	Device     string     `json:"device,omitempty"`
	Output     string     `json:"output,omitempty"`
	Items      []string   `json:"items,omitempty"`
	Theme      *ThemeInfo `json:"theme,omitempty"`
	Bands      []float64  `json:"bands,omitempty"`
}

// ThemeInfo carries the active theme name and its resolved hex colors.
// Empty hex fields mean the default (ANSI fallback) theme is active.
type ThemeInfo struct {
	Name     string `json:"name"`
	Accent   string `json:"accent,omitempty"`
	Fg       string `json:"fg,omitempty"`
	BrightFg string `json:"bright_fg,omitempty"`
	Green    string `json:"green,omitempty"`
	Yellow   string `json:"yellow,omitempty"`
	Red      string `json:"red,omitempty"`
}

// PluginDispatcher is the hook the IPC server calls to forward plugin.call and
// plugin.commands requests to the Lua plugin manager. Optional — if nil, those
// subcommands return an error.
type PluginDispatcher interface {
	EmitCommand(plugin, command string, args []string) (string, error)
	CommandList() []string
}

// TrackInfo is the track metadata in a status response.
type TrackInfo struct {
	Title  string `json:"title,omitempty"`
	Artist string `json:"artist,omitempty"`
	Path   string `json:"path"`
}

// DispatcherFunc adapts a plain function to the Dispatcher interface.
type DispatcherFunc func(msg any)

// Send implements Dispatcher.
func (f DispatcherFunc) Send(msg any) { f(msg) }

// IPC-specific messages sent to the TUI via prog.Send().
// For shared types (NextMsg, PrevMsg, StopMsg, PlayPauseMsg), see internal/playback.

// PlayMsg requests playback to start (unpause only, not toggle).
type PlayMsg struct{}

// PauseMsg requests playback to pause (pause only, not toggle).
type PauseMsg struct{}

// VolumeMsg requests a relative volume change in dB.
type VolumeMsg struct{ DB float64 }

// SeekMsg requests a relative seek.
type SeekMsg struct{ Offset time.Duration }

// LoadMsg requests loading a playlist by name.
// Reply receives the result so the client can report errors.
type LoadMsg struct {
	Playlist string
	Reply    chan Response
}

// QueueMsg requests queuing a file path for playback.
type QueueMsg struct{ Path string }

// ThemeMsg requests changing the TUI theme by name.
// Reply receives confirmation or error if theme not found.
type ThemeMsg struct {
	Name  string
	Reply chan Response
}

// VisMsg requests changing the active visualizer by name.
// If Name is "next", the visualizer cycles to the next mode.
// Reply receives confirmation or error if mode not found.
type VisMsg struct {
	Name  string
	Reply chan Response
}

// ShuffleMsg requests toggling or setting shuffle mode.
// If Name is "on"/"off", it sets the mode explicitly; "toggle" toggles.
type ShuffleMsg struct {
	Name  string
	Reply chan Response
}

// RepeatMsg requests setting or cycling the repeat mode.
// Name is "off", "all", "one", or "cycle".
type RepeatMsg struct {
	Name  string
	Reply chan Response
}

// MonoMsg requests toggling or setting mono mode.
// If Name is "on"/"off", it sets the mode explicitly; "toggle" toggles.
type MonoMsg struct {
	Name  string
	Reply chan Response
}

// SpeedMsg requests setting the playback speed.
type SpeedMsg struct {
	Speed float64
	Reply chan Response
}

// EQMsg requests setting EQ preset by name or a single band's gain.
// If Band >= 0, sets that band to Value dB. Otherwise applies preset Name.
type EQMsg struct {
	Name  string
	Band  int
	Value float64
	Reply chan Response
}

// DeviceMsg requests switching the audio output device or listing devices.
// If Name is "list", returns available devices. Otherwise switches to named device.
type DeviceMsg struct {
	Name  string
	Reply chan Response
}

// StatusRequestMsg asks the TUI for current state.
// The TUI writes the response to Reply and closes the channel.
type StatusRequestMsg struct {
	Reply chan Response
}

// BandsRequestMsg asks the TUI for the current visualizer band values
// (smoothed) and the active visualizer mode name. Lightweight compared to
// StatusRequestMsg — intended for high-rate polling from external widgets.
type BandsRequestMsg struct {
	Reply chan Response
}
