export const bluesoundDefaultPort = 11000;
export const bluesoundDefaultTimeoutMs = 5000;

export type TBluesoundSnapshotSource = 'snapshot' | 'http' | 'executor' | 'manual' | 'runtime';
export type TBluesoundPlaybackState = 'play' | 'stream' | 'pause' | 'stop' | 'unknown' | (string & {});
export type TBluesoundCommand =
  | 'play'
  | 'pause'
  | 'stop'
  | 'next_track'
  | 'previous_track'
  | 'seek'
  | 'set_volume'
  | 'mute'
  | 'select_source'
  | 'play_media'
  | 'play_preset'
  | 'clear_playlist'
  | 'shuffle'
  | 'join'
  | 'unjoin'
  | 'add_follower'
  | 'remove_follower';

export interface IBluesoundConfig {
  host?: string;
  port?: number;
  name?: string;
  macAddress?: string;
  manufacturer?: string;
  model?: string;
  modelName?: string;
  timeoutMs?: number;
  snapshot?: IBluesoundSnapshot;
  commandExecutor?: IBluesoundCommandExecutor;
}

export interface IHomeAssistantBluesoundConfig extends IBluesoundConfig {}

export interface IBluesoundCommandExecutor {
  execute(requestArg: IBluesoundRawCommandRequest): Promise<IBluesoundRawCommandResponse | Record<string, unknown> | unknown>;
}

export interface IBluesoundRawCommandRequest {
  method: 'GET';
  command: string;
  path: string;
  parameters: Record<string, string | number | boolean>;
  url?: string;
  host?: string;
  port: number;
}

export interface IBluesoundRawCommandResponse {
  status?: number;
  body?: string;
  data?: unknown;
}

export interface IBluesoundCommandRequest {
  command: TBluesoundCommand;
  playerId?: string;
  playerIds?: string[];
  followers?: IBluesoundPairedPlayer[];
  follower?: IBluesoundPairedPlayer;
  source?: string;
  presetId?: number;
  presetName?: string;
  mediaId?: string;
  mediaType?: string;
  volumeLevel?: number;
  volume?: number;
  muted?: boolean;
  shuffle?: boolean;
  position?: number;
}

export interface IBluesoundPairedPlayer {
  ip: string;
  port: number;
}

export interface IBluesoundStatus {
  etag?: string;
  inputId?: string;
  service?: string;
  state: TBluesoundPlaybackState;
  shuffle?: boolean;
  album?: string;
  artist?: string;
  name?: string;
  image?: string;
  volume?: number;
  volumeDb?: number;
  mute?: boolean;
  muteVolume?: number;
  muteVolumeDb?: number;
  seconds?: number;
  totalSeconds?: number;
  canSeek?: boolean;
  sleep?: number;
  groupName?: string;
  groupVolume?: number;
  indexing?: boolean;
  streamUrl?: string;
  raw?: Record<string, unknown>;
}

export interface IBluesoundSyncStatus {
  etag?: string;
  id: string;
  mac: string;
  name: string;
  image?: string;
  initialized?: boolean;
  group?: string;
  leader?: IBluesoundPairedPlayer;
  followers?: IBluesoundPairedPlayer[];
  zone?: string;
  zoneLeader?: boolean;
  zoneFollower?: boolean;
  brand?: string;
  model?: string;
  modelName?: string;
  muteVolumeDb?: number;
  muteVolume?: number;
  volumeDb?: number;
  volume?: number;
  raw?: Record<string, unknown>;
}

export interface IBluesoundPreset {
  name: string;
  id: number;
  url: string;
  image?: string;
  volume?: number;
}

export interface IBluesoundInput {
  id?: string;
  text?: string;
  image?: string;
  url: string;
}

export interface IBluesoundPlayerSnapshot {
  host?: string;
  port?: number;
  syncStatus: IBluesoundSyncStatus;
  status: IBluesoundStatus;
  presets?: IBluesoundPreset[];
  inputs?: IBluesoundInput[];
  available?: boolean;
  updatedAt?: string;
}

export interface IBluesoundSnapshot {
  players: IBluesoundPlayerSnapshot[];
  online: boolean;
  updatedAt?: string;
  source?: TBluesoundSnapshotSource;
  error?: string;
}

export interface IBluesoundMdnsRecord {
  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 IBluesoundManualEntry {
  host?: string;
  port?: number;
  id?: string;
  name?: string;
  manufacturer?: string;
  model?: string;
  modelName?: string;
  macAddress?: string;
  metadata?: Record<string, unknown>;
}
