export const squeezeboxDefaultHttpPort = 9000;
export const squeezeboxDefaultCliPort = 9090;
export const squeezeboxDefaultTimeoutMs = 5000;
export const squeezeboxDefaultBrowseLimit = 1000;
export const squeezeboxDefaultVolumeStep = 5;

export type TSqueezeboxTransport = 'jsonrpc' | 'cli' | 'snapshot';
export type TSqueezeboxSnapshotSource = 'snapshot' | 'jsonrpc' | 'cli' | 'executor' | 'runtime' | 'manual';
export type TSqueezeboxPlaybackMode = 'play' | 'pause' | 'stop' | 'unknown' | (string & {});
export type TSqueezeboxRepeatMode = 'none' | 'song' | 'playlist' | (string & {});
export type TSqueezeboxShuffleMode = 'none' | 'song' | 'album' | (string & {});
export type TSqueezeboxMediaCommand =
  | 'play'
  | 'pause'
  | 'play_pause'
  | 'stop'
  | 'next_track'
  | 'previous_track'
  | 'seek'
  | 'set_power'
  | 'set_volume'
  | 'volume_up'
  | 'volume_down'
  | 'mute'
  | 'select_source'
  | 'play_media'
  | 'sync'
  | 'unsync'
  | 'raw_query';

export interface ISqueezeboxConfig {
  host?: string;
  port?: number;
  cliPort?: number;
  username?: string;
  password?: string;
  https?: boolean;
  name?: string;
  serverId?: string;
  timeoutMs?: number;
  browseLimit?: number;
  volumeStep?: number;
  transport?: TSqueezeboxTransport;
  snapshot?: ISqueezeboxSnapshot;
  commandExecutor?: ISqueezeboxCommandExecutor;
}

export interface IHomeAssistantSqueezeboxConfig extends ISqueezeboxConfig {}

export interface ISqueezeboxCommandExecutor {
  execute(requestArg: ISqueezeboxRawCommandRequest): Promise<ISqueezeboxJsonRpcResponse | ISqueezeboxCliResponse | Record<string, unknown> | unknown>;
}

export interface ISqueezeboxRawCommandRequest {
  transport: Exclude<TSqueezeboxTransport, 'snapshot'>;
  host?: string;
  port: number;
  endpoint?: string;
  playerId?: string;
  command: string[];
  body?: ISqueezeboxJsonRpcRequest;
  cliLine?: string;
}

export interface ISqueezeboxJsonRpcRequest {
  id: number | string;
  method: 'slim.request';
  params: [string | 0, string[]];
}

export interface ISqueezeboxJsonRpcError {
  code?: number;
  message?: string;
  data?: unknown;
}

export interface ISqueezeboxJsonRpcResponse<TResult = Record<string, unknown>> {
  id?: number | string;
  method?: string;
  params?: unknown[];
  result?: TResult;
  error?: ISqueezeboxJsonRpcError | string;
}

export interface ISqueezeboxCliResponse {
  playerId?: string;
  command: string[];
  rawLine: string;
  tokens: string[];
  result: Record<string, unknown>;
}

export interface ISqueezeboxCommandRequest {
  command: TSqueezeboxMediaCommand;
  playerId?: string;
  targetPlayerId?: string;
  playerIds?: string[];
  volumeLevel?: number;
  volume?: number;
  step?: number;
  muted?: boolean;
  powered?: boolean;
  source?: string;
  mediaId?: string;
  mediaType?: string;
  enqueue?: 'play' | 'add' | 'next';
  position?: number;
  parameters?: Array<string | number | boolean>;
}

export interface ISqueezeboxServerInfo {
  id?: string;
  uuid?: string;
  mac?: string;
  name?: string;
  libraryName?: string;
  host?: string;
  port?: number;
  version?: string;
  manufacturer?: string;
  model?: string;
  playerCount?: number;
  otherPlayerCount?: number;
  rescan?: boolean;
  needsRestart?: boolean;
  stats?: {
    totalAlbums?: number;
    totalArtists?: number;
    totalDuration?: number;
    totalGenres?: number;
    totalSongs?: number;
    lastScan?: string | number;
  };
  raw?: Record<string, unknown>;
}

export interface ISqueezeboxTrack {
  id?: string | number;
  url?: string;
  title?: string;
  artist?: string;
  album?: string;
  duration?: number;
  remoteTitle?: string;
  imageUrl?: string;
  raw?: Record<string, unknown>;
}

export interface ISqueezeboxAlarm {
  id: string;
  enabled?: boolean;
  time?: string;
  repeat?: boolean;
  scheduledToday?: boolean;
  daysOfWeek?: number[];
  volume?: number;
  url?: string;
  raw?: Record<string, unknown>;
}

export interface ISqueezeboxPlayer {
  playerId: string;
  uuid?: string;
  name: string;
  model?: string;
  modelType?: string;
  manufacturer?: string;
  creator?: string;
  firmware?: string;
  ipAddress?: string;
  connected?: boolean;
  power?: boolean;
  mode?: TSqueezeboxPlaybackMode;
  volume?: number;
  muting?: boolean;
  repeat?: TSqueezeboxRepeatMode;
  shuffle?: TSqueezeboxShuffleMode;
  time?: number;
  duration?: number;
  title?: string;
  remoteTitle?: string;
  artist?: string;
  album?: string;
  url?: string;
  imageUrl?: string;
  playlist?: ISqueezeboxTrack[];
  currentIndex?: number;
  alarms?: ISqueezeboxAlarm[];
  alarmsEnabled?: boolean;
  alarmNext?: string;
  syncGroup?: string[];
  source?: string;
  available?: boolean;
  raw?: Record<string, unknown>;
}

export interface ISqueezeboxFavorite {
  id: string;
  name: string;
  type?: string;
  url?: string;
  itemId?: string;
  imageUrl?: string;
  playable?: boolean;
  raw?: Record<string, unknown>;
}

export interface ISqueezeboxSyncGroup {
  id: string;
  name?: string;
  playerIds: string[];
  leaderPlayerId?: string;
  raw?: Record<string, unknown>;
}

export interface ISqueezeboxSnapshot {
  server: ISqueezeboxServerInfo;
  players: ISqueezeboxPlayer[];
  favorites?: ISqueezeboxFavorite[];
  syncGroups?: ISqueezeboxSyncGroup[];
  online: boolean;
  updatedAt?: string;
  source?: TSqueezeboxSnapshotSource;
  error?: string;
  raw?: Record<string, unknown>;
}

export interface ISqueezeboxMdnsRecord {
  name?: string;
  type?: string;
  serviceType?: string;
  host?: string;
  hostname?: string;
  port?: number;
  addresses?: string[];
  txt?: Record<string, string | undefined>;
  properties?: Record<string, string | undefined>;
}

export interface ISqueezeboxDhcpRecord {
  hostname?: string;
  macaddress?: string;
  macAddress?: string;
  ipAddress?: string;
  host?: string;
  name?: string;
  metadata?: Record<string, unknown>;
}

export interface ISqueezeboxManualEntry {
  host?: string;
  port?: number;
  cliPort?: number;
  id?: string;
  name?: string;
  username?: string;
  password?: string;
  https?: boolean;
  manufacturer?: string;
  model?: string;
  metadata?: Record<string, unknown>;
}
