export const denonDomain = 'denon';
export const denonDefaultName = 'Music station';
export const denonDefaultPort = 23;
export const denonDefaultTimeoutMs = 1500;

export type TDenonSnapshotSource = 'telnet' | 'snapshot' | 'manual' | 'client' | 'executor' | 'runtime';

export type TDenonPowerState = 'PWON' | 'PWSTANDBY' | string;

export type TDenonMediaState = 'on' | 'off' | 'playing' | 'paused' | 'idle' | 'unavailable' | string;

export type TDenonCommand =
  | 'turn_on'
  | 'turn_off'
  | 'volume_up'
  | 'volume_down'
  | 'set_volume'
  | 'mute'
  | 'select_source'
  | 'play'
  | 'pause'
  | 'stop'
  | 'next_track'
  | 'previous_track'
  | 'raw';

export interface IDenonConfig {
  host?: string;
  port?: number;
  name?: string;
  manufacturer?: string;
  model?: string;
  serialNumber?: string;
  timeoutMs?: number;
  responseIdleMs?: number;
  sourceMap?: Record<string, string>;
  snapshot?: IDenonSnapshot;
  client?: IDenonClientLike;
  commandExecutor?: IDenonCommandExecutor;
}

export interface IHomeAssistantDenonConfig extends IDenonConfig {}

export interface IDenonClientLike {
  getSnapshot?(): Promise<IDenonSnapshot>;
  snapshot?(): Promise<IDenonSnapshot>;
  execute?(requestArg: IDenonCommandRequest): Promise<unknown>;
}

export interface IDenonCommandExecutor {
  execute(requestArg: IDenonRawCommandRequest): Promise<unknown>;
}

export interface IDenonReceiverInfo {
  host?: string;
  port?: number;
  name?: string;
  manufacturer?: string;
  modelName?: string;
  serialNumber?: string;
}

export interface IDenonMediaPlayerState {
  power?: TDenonPowerState;
  state?: TDenonMediaState;
  volume?: number;
  volumeMax?: number;
  volumeLevel?: number;
  muted?: boolean;
  source?: string;
  sourceName?: string;
  sourceList?: string[];
  mediaTitle?: string;
  mediaInfo?: string;
  mediaMode?: boolean;
  supportedFeatures?: string[];
}

export interface IDenonSnapshot {
  receiverInfo: IDenonReceiverInfo;
  state: IDenonMediaPlayerState;
  sourceMap?: Record<string, string>;
  online: boolean;
  available: boolean;
  source: TDenonSnapshotSource;
  lastUpdated?: string;
  error?: string;
}

export interface IDenonCommandRequest {
  command: TDenonCommand;
  source?: string;
  volumeLevel?: number;
  muted?: boolean;
  rawCommand?: string;
}

export interface IDenonRawCommandRequest {
  command: 'raw';
  rawCommand: string;
  host?: string;
  port: number;
  timeoutMs: number;
}

export interface IDenonManualEntry {
  host?: string;
  port?: number;
  id?: string;
  name?: string;
  manufacturer?: string;
  model?: string;
  serialNumber?: string;
  sourceMap?: Record<string, string>;
  snapshot?: IDenonSnapshot;
  client?: IDenonClientLike;
  commandExecutor?: IDenonCommandExecutor;
  metadata?: Record<string, unknown>;
}

export const denonNormalInputs: Record<string, string> = {
  Cd: 'CD',
  Dvd: 'DVD',
  'Blue ray': 'BD',
  TV: 'TV',
  'Satellite / Cable': 'SAT/CBL',
  Game: 'GAME',
  Game2: 'GAME2',
  'Video Aux': 'V.AUX',
  Dock: 'DOCK',
};

export const denonMediaModes: Record<string, string> = {
  Tuner: 'TUNER',
  'Media server': 'SERVER',
  'Ipod dock': 'IPOD',
  'Net/USB': 'NET/USB',
  Rapsody: 'RHAPSODY',
  Napster: 'NAPSTER',
  Pandora: 'PANDORA',
  LastFM: 'LASTFM',
  Flickr: 'FLICKR',
  Favorites: 'FAVORITES',
  'Internet Radio': 'IRADIO',
  'USB/IPOD': 'USB/IPOD',
  USB: 'USB',
};

export const denonDefaultSourceMap: Record<string, string> = {
  ...denonNormalInputs,
  ...denonMediaModes,
};

export const denonMediaModeCodes = new Set(Object.values(denonMediaModes));
