export const arcamFmjDefaultPort = 50000;

export type TArcamFmjApiModel =
  | 'API450_SERIES'
  | 'API860_SERIES'
  | 'APIHDA_SERIES'
  | 'APISA_SERIES'
  | 'APIPA_SERIES'
  | 'APIST_SERIES';

export type TArcamFmjSnapshotSource = 'manual' | 'snapshot' | 'tcp';

export type TArcamFmjCommand =
  | 'turn_on'
  | 'turn_off'
  | 'volume_up'
  | 'volume_down'
  | 'set_volume'
  | 'mute'
  | 'select_source'
  | 'raw_command';

export type TArcamFmjSource =
  | 'FOLLOW_ZONE_1'
  | 'CD'
  | 'BD'
  | 'AV'
  | 'SAT'
  | 'PVR'
  | 'VCR'
  | 'AUX'
  | 'DISPLAY'
  | 'FM'
  | 'DAB'
  | 'NET'
  | 'USB'
  | 'STB'
  | 'GAME'
  | 'PHONO'
  | 'ARC_ERC'
  | 'UHD'
  | 'BT'
  | 'DIG1'
  | 'DIG2'
  | 'DIG3'
  | 'DIG4'
  | 'NET_USB'
  | (string & {});

export interface IArcamFmjConfig {
  host?: string;
  port?: number;
  name?: string;
  manufacturer?: string;
  model?: string;
  revision?: string;
  serialNumber?: string;
  uniqueId?: string;
  apiModel?: TArcamFmjApiModel;
  zones?: IArcamFmjZoneState[];
  requestTimeoutMs?: number;
  sourceMap?: Record<string, string>;
  commandExecutor?: IArcamFmjCommandExecutor;
  snapshot?: IArcamFmjSnapshot;
}

export interface IHomeAssistantArcamFmjConfig extends IArcamFmjConfig {}

export interface IArcamFmjCommandExecutor {
  execute(commandArg: IArcamFmjModeledCommand): Promise<unknown>;
}

export interface IArcamFmjDeviceInfo {
  host?: string;
  port?: number;
  name?: string;
  manufacturer?: string;
  model?: string;
  revision?: string;
  serialNumber?: string;
  uniqueId?: string;
  apiModel?: TArcamFmjApiModel;
  amx?: Record<string, string>;
}

export interface IArcamFmjIncomingVideoParameters {
  horizontalResolution?: number;
  verticalResolution?: number;
  refreshRate?: number;
  interlaced?: boolean;
  aspectRatio?: string;
  colorspace?: string;
}

export interface IArcamFmjIncomingAudioInfo {
  format?: string;
  config?: string;
  sampleRate?: number;
}

export interface IArcamFmjPresetDetail {
  index: number;
  type?: string | number;
  name: string;
}

export interface IArcamFmjMediaInfo {
  title?: string;
  artist?: string;
  channel?: string;
  contentType?: string;
  contentId?: string;
}

export interface IArcamFmjZoneState {
  zone: number;
  name?: string;
  power?: boolean;
  state?: 'on' | 'off' | string;
  volume?: number;
  volumeLevel?: number;
  muted?: boolean;
  source?: TArcamFmjSource;
  sourceList?: TArcamFmjSource[];
  soundMode?: string;
  soundModeList?: string[];
  incomingVideo?: IArcamFmjIncomingVideoParameters;
  incomingAudio?: IArcamFmjIncomingAudioInfo;
  dabStation?: string;
  dlsPdt?: string;
  rdsInformation?: string;
  tunerPreset?: number;
  presets?: IArcamFmjPresetDetail[];
  media?: IArcamFmjMediaInfo;
  available?: boolean;
}

export interface IArcamFmjSnapshot {
  deviceInfo: IArcamFmjDeviceInfo;
  zones: IArcamFmjZoneState[];
  online?: boolean;
  source?: TArcamFmjSnapshotSource;
  lastUpdated?: string;
}

export interface IArcamFmjCommandRequest {
  command: TArcamFmjCommand;
  zone?: number;
  source?: string;
  volumeLevel?: number;
  volume?: number;
  muted?: boolean;
  commandCode?: number;
  data?: number[];
  sendOnly?: boolean;
}

export interface IArcamFmjModeledCommand {
  command: TArcamFmjCommand;
  zone: number;
  apiModel: TArcamFmjApiModel;
  commandCode: number;
  commandCodeName: string;
  data: number[];
  dataHex: string;
  sendOnly: boolean;
  responseExpected: boolean;
  usesRc5: boolean;
  source?: string;
  volumeLevel?: number;
  muted?: boolean;
}

export interface IArcamFmjResponsePacket {
  zone: number;
  commandCode: number;
  commandCodeName: string;
  answerCode: number;
  data: number[];
  dataHex: string;
}

export interface IArcamFmjCommandResult {
  transport: 'tcp' | 'executor';
  modeledCommand: IArcamFmjModeledCommand;
  response?: IArcamFmjResponsePacket;
  executorResult?: unknown;
}

export interface IArcamFmjSsdpRecord {
  st?: string;
  usn?: string;
  location?: string;
  headers?: Record<string, string | undefined>;
  upnp?: Record<string, string | undefined>;
}

export interface IArcamFmjManualEntry {
  host?: string;
  port?: number;
  id?: string;
  name?: string;
  manufacturer?: string;
  model?: string;
  serialNumber?: string;
  metadata?: Record<string, unknown>;
}
