export const madvrDefaultPort = 44077;

export type TMadvrPowerState = 'on' | 'off' | 'unknown';

export type TMadvrCommandName =
  | 'PowerOn'
  | 'PowerOff'
  | 'Standby'
  | 'Restart'
  | 'ReloadSoftware'
  | 'Bye'
  | 'ResetTemporary'
  | 'ActivateProfile'
  | 'OpenMenu'
  | 'CloseMenu'
  | 'KeyPress'
  | 'KeyHold'
  | 'GetIncomingSignalInfo'
  | 'GetOutgoingSignalInfo'
  | 'GetAspectRatio'
  | 'GetMaskingRatio'
  | 'GetTemperatures'
  | 'GetMacAddress'
  | 'Toggle'
  | 'ToneMapOn'
  | 'ToneMapOff'
  | 'Hotplug'
  | 'RefreshLicenseInfo'
  | 'Force1080p60Output';

export type TMadvrRemoteKey =
  | 'MENU'
  | 'UP'
  | 'DOWN'
  | 'LEFT'
  | 'RIGHT'
  | 'OK'
  | 'INPUT'
  | 'SETTINGS'
  | 'RED'
  | 'GREEN'
  | 'BLUE'
  | 'YELLOW'
  | 'POWER';

export type TMadvrMenu = 'Info' | 'Settings' | 'Configuration' | 'Profiles' | 'TestPatterns';

export type TMadvrProfileGroup = 'SOURCE' | 'DISPLAY' | 'CUSTOM';

export type TMadvrToggle =
  | 'ToneMap'
  | 'HighlightRecovery'
  | 'ContrastRecovery'
  | 'ShadowRecovery'
  | '3DLUT'
  | 'ScreenBoundaries'
  | 'Histogram'
  | 'DebugOSD';

export interface IMadvrSignalState {
  resolution?: string;
  frameRate?: string;
  signalType?: '2D' | '3D' | string;
  colorSpace?: 'RGB' | '444' | '422' | '420' | string;
  bitDepth?: '8bit' | '10bit' | '12bit' | string;
  hdr?: boolean;
  colorimetry?: 'SDR' | 'HDR10' | 'HLG 601' | 'PAL' | '709' | 'DCI' | '2020' | string;
  blackLevels?: 'TV' | 'PC' | string;
  aspectRatio?: '16:9' | '4:3' | string;
}

export interface IMadvrTemperatures {
  gpu?: number;
  hdmi?: number;
  cpu?: number;
  mainboard?: number;
}

export interface IMadvrRatioState {
  resolution?: string;
  decimal?: number;
  integer?: string;
  name?: string;
}

export interface IMadvrProcessorState {
  isOn?: boolean;
  isSignal?: boolean;
  power?: TMadvrPowerState;
  incoming?: IMadvrSignalState;
  outgoing?: IMadvrSignalState;
  temperatures?: IMadvrTemperatures;
  profileName?: string;
  profileNumber?: string;
  lastError?: string;
  raw?: Record<string, unknown>;
}

export interface IMadvrProjectorState {
  name?: string;
  activeProfile?: string;
  profileName?: string;
  profileNumber?: string;
  metadata?: Record<string, unknown>;
}

export interface IMadvrDisplayState {
  hdrFlag?: boolean;
  outgoingHdrFlag?: boolean;
  aspect?: IMadvrRatioState;
  masking?: IMadvrRatioState;
  activeProfile?: string;
}

export interface IMadvrDeviceInfo {
  host?: string;
  port?: number;
  name?: string;
  manufacturer?: string;
  model?: string;
  macAddress?: string;
  serialNumber?: string;
  firmwareVersion?: string;
}

export interface IMadvrRawState {
  is_on?: boolean;
  isOn?: boolean;
  is_signal?: boolean;
  isSignal?: boolean;
  hdr_flag?: boolean;
  hdrFlag?: boolean;
  outgoing_hdr_flag?: boolean;
  outgoingHdrFlag?: boolean;
  mac_address?: string;
  macAddress?: string;
  temp_gpu?: string | number | null;
  tempGpu?: string | number | null;
  temp_hdmi?: string | number | null;
  tempHdmi?: string | number | null;
  temp_cpu?: string | number | null;
  tempCpu?: string | number | null;
  temp_mainboard?: string | number | null;
  tempMainboard?: string | number | null;
  incoming_res?: string;
  incomingRes?: string;
  incoming_signal_type?: string;
  incomingSignalType?: string;
  incoming_frame_rate?: string;
  incomingFrameRate?: string;
  incoming_color_space?: string;
  incomingColorSpace?: string;
  incoming_bit_depth?: string;
  incomingBitDepth?: string;
  incoming_colorimetry?: string;
  incomingColorimetry?: string;
  incoming_black_levels?: string;
  incomingBlackLevels?: string;
  incoming_aspect_ratio?: string;
  incomingAspectRatio?: string;
  outgoing_res?: string;
  outgoingRes?: string;
  outgoing_signal_type?: string;
  outgoingSignalType?: string;
  outgoing_frame_rate?: string;
  outgoingFrameRate?: string;
  outgoing_color_space?: string;
  outgoingColorSpace?: string;
  outgoing_bit_depth?: string;
  outgoingBitDepth?: string;
  outgoing_colorimetry?: string;
  outgoingColorimetry?: string;
  outgoing_black_levels?: string;
  outgoingBlackLevels?: string;
  aspect_res?: string;
  aspectRes?: string;
  aspect_dec?: string | number | null;
  aspectDec?: string | number | null;
  aspect_int?: string;
  aspectInt?: string;
  aspect_name?: string;
  aspectName?: string;
  masking_res?: string;
  maskingRes?: string;
  masking_dec?: string | number | null;
  maskingDec?: string | number | null;
  masking_int?: string;
  maskingInt?: string;
  profile_name?: string;
  profileName?: string;
  profile_num?: string | number;
  profileNumber?: string | number;
  [key: string]: unknown;
}

export interface IMadvrCommandRequest {
  command: TMadvrCommandName | string;
  args?: string[];
  source?: string;
  target?: Record<string, unknown>;
}

export type TMadvrCommandInput = string | string[] | IMadvrCommandRequest;

export interface IMadvrCommandModel {
  request: IMadvrCommandRequest;
  transport: 'tcp' | 'wake_on_lan';
  wireCommand?: string;
  informational: boolean;
  requiresConnection: boolean;
  description?: string;
}

export interface IMadvrCommandResult {
  executed: boolean;
  command: IMadvrCommandModel;
  transport?: 'tcp' | 'wake_on_lan' | 'executor';
  response?: string;
  data?: unknown;
}

export interface IMadvrCommandExecutor {
  execute(commandArg: IMadvrCommandRequest, modelArg: IMadvrCommandModel): Promise<IMadvrCommandResult | string | void>;
  getSnapshot?(): Promise<IMadvrSnapshot>;
  destroy?(): Promise<void>;
}

export interface IMadvrButtonRecord {
  key: string;
  name: string;
  command: TMadvrCommandInput;
  entityCategory?: string;
  icon?: string;
  available?: boolean;
}

export interface IMadvrSelectRecord {
  key: string;
  name: string;
  current?: string;
  options: string[];
  command?: TMadvrCommandInput;
  commands?: Record<string, TMadvrCommandInput>;
  entityCategory?: string;
  available?: boolean;
}

export interface IMadvrSnapshot {
  deviceInfo: IMadvrDeviceInfo;
  processor: IMadvrProcessorState;
  projector?: IMadvrProjectorState;
  display: IMadvrDisplayState;
  buttons?: IMadvrButtonRecord[];
  selects?: IMadvrSelectRecord[];
  raw?: IMadvrRawState;
  available?: boolean;
  updatedAt?: string;
}

export interface IMadvrConfig {
  host?: string;
  port?: number;
  name?: string;
  model?: string;
  manufacturer?: string;
  macAddress?: string;
  serialNumber?: string;
  state?: IMadvrRawState;
  processor?: IMadvrProcessorState;
  projector?: IMadvrProjectorState;
  display?: IMadvrDisplayState;
  buttons?: IMadvrButtonRecord[];
  selects?: IMadvrSelectRecord[];
  snapshot?: IMadvrSnapshot;
  commandExecutor?: IMadvrCommandExecutor;
  connectTimeoutMs?: number;
  commandTimeoutMs?: number;
  snapshotCollectMs?: number;
  wolBroadcastAddress?: string;
  wolPort?: number;
}

export interface IHomeAssistantMadvrConfig extends IMadvrConfig {}

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

export interface IMadvrMdnsRecord {
  type?: string;
  name?: string;
  host?: string;
  port?: number;
  txt?: Record<string, string | undefined>;
  properties?: Record<string, string | undefined>;
}

export type TMadvrDiscoveryRecord = IMadvrManualEntry | IMadvrMdnsRecord;
