export const amcrestDefaultPort = 80;
export const amcrestDefaultRtspPort = 554;
export const amcrestDefaultTimeoutMs = 10000;
export const amcrestDefaultSnapshotTimeoutMs = 20000;

export const amcrestResolutionSubtype = {
  high: 0,
  low: 1,
} as const;

export const amcrestSubtypeStream = {
  0: 'Main',
  1: 'Extra',
} as const;

export const amcrestColorModes = ['color', 'auto', 'bw'] as const;
export const amcrestStreamSources = ['snapshot', 'mjpeg', 'rtsp'] as const;
export const amcrestPtzMovements = [
  'zoom_out',
  'zoom_in',
  'right',
  'left',
  'up',
  'down',
  'right_down',
  'right_up',
  'left_down',
  'left_up',
] as const;

export type TAmcrestProtocol = 'http' | 'https';
export type TAmcrestAuthScheme = 'auto' | 'basic' | 'digest';
export type TAmcrestResolution = keyof typeof amcrestResolutionSubtype;
export type TAmcrestStreamSource = typeof amcrestStreamSources[number];
export type TAmcrestColorBw = typeof amcrestColorModes[number];
export type TAmcrestPtzMovement = typeof amcrestPtzMovements[number];
export type TAmcrestSwitchCommand = 'privacy_mode';
export type TAmcrestHttpMethod = 'GET';
export type TAmcrestCommandType =
  | 'refresh'
  | 'stream_source'
  | 'snapshot_image'
  | 'set_privacy_mode'
  | 'set_video'
  | 'set_recording'
  | 'set_audio'
  | 'set_motion_detection'
  | 'set_motion_recording'
  | 'set_color_bw'
  | 'goto_preset'
  | 'ptz_control'
  | 'start_tour'
  | 'stop_tour';

export interface IAmcrestConfig {
  protocol?: TAmcrestProtocol;
  host?: string;
  port?: number;
  url?: string;
  rtspPort?: number;
  username?: string;
  password?: string;
  authScheme?: TAmcrestAuthScheme;
  timeoutMs?: number;
  snapshotTimeoutMs?: number;
  name?: string;
  uniqueId?: string;
  manufacturer?: string;
  model?: string;
  channel?: number;
  resolution?: TAmcrestResolution;
  streamSource?: TAmcrestStreamSource;
  controlLight?: boolean;
  ffmpegArguments?: string;
  supportsPtz?: boolean;
  connected?: boolean;
  deviceInfo?: IAmcrestDeviceInfo;
  cameras?: IAmcrestCamera[];
  sensors?: IAmcrestSensor[];
  binarySensors?: IAmcrestBinarySensor[];
  switches?: IAmcrestSwitch[];
  events?: IAmcrestEvent[];
  enabledSensors?: string[];
  enabledBinarySensors?: string[];
  enabledSwitches?: string[];
  currentSettings?: Record<string, unknown>;
  snapshot?: IAmcrestSnapshot;
}

export interface IHomeAssistantAmcrestConfig extends IAmcrestConfig {}

export interface IAmcrestDeviceInfo {
  id?: string;
  name?: string;
  manufacturer?: string;
  model?: string;
  serialNumber?: string;
  macAddress?: string;
  firmwareVersion?: string;
  host?: string;
  port?: number;
  protocol?: TAmcrestProtocol;
  rtspPort?: number;
  url?: string;
  online?: boolean;
}

export interface IAmcrestCamera {
  id: string;
  name?: string;
  channel: number;
  resolution: TAmcrestResolution;
  subtype: 0 | 1;
  streamSource: TAmcrestStreamSource;
  snapshotUrl?: string;
  mjpegUrl?: string;
  rtspUrl?: string;
  available?: boolean;
  isStreaming?: boolean;
  isRecording?: boolean;
  motionDetectionEnabled?: boolean;
  audioEnabled?: boolean;
  motionRecordingEnabled?: boolean;
  colorBw?: TAmcrestColorBw;
  supportsPtz?: boolean;
  attributes?: Record<string, unknown>;
}

export interface IAmcrestSensor<TValue = unknown> {
  key: string;
  name: string;
  value: TValue;
  unit?: string;
  deviceClass?: string;
  entityCategory?: string;
  available?: boolean;
  attributes?: Record<string, unknown>;
}

export interface IAmcrestBinarySensor {
  key: string;
  name: string;
  isOn: boolean;
  deviceClass?: string;
  eventCodes?: string[];
  shouldPoll?: boolean;
  available?: boolean;
  attributes?: Record<string, unknown>;
}

export interface IAmcrestSwitch {
  key: string;
  name: string;
  isOn: boolean;
  command: TAmcrestSwitchCommand;
  entityCategory?: string;
  available?: boolean;
  attributes?: Record<string, unknown>;
}

export interface IAmcrestEvent {
  id: string;
  name?: string;
  code?: string;
  state?: string;
  isOn?: boolean;
  updatedAt?: string;
  payload?: Record<string, unknown>;
}

export interface IAmcrestSnapshot {
  deviceInfo: IAmcrestDeviceInfo;
  cameras: IAmcrestCamera[];
  sensors: IAmcrestSensor[];
  binarySensors: IAmcrestBinarySensor[];
  switches: IAmcrestSwitch[];
  events: IAmcrestEvent[];
  currentSettings: Record<string, unknown>;
  connected: boolean;
  updatedAt?: string;
  metadata?: Record<string, unknown>;
}

export interface IAmcrestHttpCommand {
  label: string;
  method: TAmcrestHttpMethod;
  path: string;
  expect?: 'ok' | 'image' | 'text';
}

export interface IAmcrestCommandResponse {
  ok: boolean;
  label: string;
  method: TAmcrestHttpMethod;
  path: string;
  status: number;
  responseText?: string;
}

export interface IAmcrestClientCommand {
  type: TAmcrestCommandType;
  service: string;
  target?: {
    entityId?: string;
    deviceId?: string;
  };
  data?: Record<string, unknown>;
  cameraId?: string;
  channel?: number;
  resolution?: TAmcrestResolution;
  streamSource?: TAmcrestStreamSource;
  filename?: string;
  enabled?: boolean;
  preset?: number;
  colorBw?: TAmcrestColorBw;
  movement?: TAmcrestPtzMovement;
  travelTime?: number;
  httpCommands?: IAmcrestHttpCommand[];
}

export interface IAmcrestSnapshotImage {
  contentType: string;
  data: Uint8Array;
}

export interface IAmcrestSensorDescription {
  key: string;
  name: string;
  unit?: string;
  deviceClass?: string;
  entityCategory?: string;
}

export interface IAmcrestBinarySensorDescription {
  key: string;
  name: string;
  deviceClass?: string;
  eventCodes?: string[];
  shouldPoll?: boolean;
}

export interface IAmcrestSwitchDescription {
  key: string;
  name: string;
  command: TAmcrestSwitchCommand;
  entityCategory?: string;
}

export interface IAmcrestManualEntry {
  host?: string;
  port?: number;
  url?: string;
  protocol?: TAmcrestProtocol;
  username?: string;
  password?: string;
  id?: string;
  name?: string;
  manufacturer?: string;
  model?: string;
  serialNumber?: string;
  macAddress?: string;
  metadata?: Record<string, unknown>;
}

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

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

export const amcrestSensorDescriptions: IAmcrestSensorDescription[] = [
  { key: 'ptz_preset', name: 'PTZ Preset', entityCategory: 'diagnostic' },
  { key: 'sdcard', name: 'SD Used', unit: '%', entityCategory: 'diagnostic' },
];

export const amcrestBinarySensorDescriptions: IAmcrestBinarySensorDescription[] = [
  { key: 'audio_detected', name: 'Audio Detected', deviceClass: 'sound', eventCodes: ['AudioMutation', 'AudioIntensity'] },
  { key: 'audio_detected_polled', name: 'Audio Detected', deviceClass: 'sound', eventCodes: ['AudioMutation', 'AudioIntensity'], shouldPoll: true },
  { key: 'crossline_detected', name: 'CrossLine Detected', deviceClass: 'motion', eventCodes: ['CrossLineDetection'] },
  { key: 'crossline_detected_polled', name: 'CrossLine Detected', deviceClass: 'motion', eventCodes: ['CrossLineDetection'], shouldPoll: true },
  { key: 'motion_detected', name: 'Motion Detected', deviceClass: 'motion', eventCodes: ['VideoMotion'] },
  { key: 'motion_detected_polled', name: 'Motion Detected', deviceClass: 'motion', eventCodes: ['VideoMotion'], shouldPoll: true },
  { key: 'online', name: 'Online', deviceClass: 'connectivity', shouldPoll: true },
];

export const amcrestSwitchDescriptions: IAmcrestSwitchDescription[] = [
  { key: 'privacy_mode', name: 'Privacy Mode', command: 'privacy_mode', entityCategory: 'config' },
];
