export const hyperionDomain = 'hyperion';
export const hyperionDisplayName = 'Hyperion';
export const hyperionDefaultJsonPort = 19444;
export const hyperionDefaultWebPort = 8090;
export const hyperionDefaultSslWebPort = 8092;
export const hyperionDefaultTimeoutMs = 10000;
export const hyperionDefaultPriority = 128;
export const hyperionDefaultOrigin = 'smarthome.exchange';
export const hyperionSolidEffect = 'Solid';
export const hyperionSsdpManufacturer = 'Hyperion Open Source Ambient Lighting';
export const hyperionSsdpServiceType = 'urn:hyperion-project.org:device:basic:1';

export const hyperionComponentIds = [
  'ALL',
  'SMOOTHING',
  'BLACKBORDER',
  'FORWARDER',
  'BOBLIGHTSERVER',
  'GRABBER',
  'LEDDEVICE',
  'V4L',
  'AUDIO',
] as const;

export type THyperionTransport = 'tcp' | 'http' | 'websocket';
export type THyperionSnapshotSource = 'tcp' | 'http' | 'websocket' | 'client' | 'manual' | 'snapshot' | 'runtime' | 'executor';
export type THyperionComponentId = typeof hyperionComponentIds[number] | string;
export type THyperionImageFormat = 'BMP' | 'JPG' | 'PNG';
export type THyperionCommandAction =
  | 'refresh'
  | 'set_color'
  | 'set_effect'
  | 'clear'
  | 'set_component'
  | 'adjust_brightness'
  | 'get_image_snapshot'
  | 'image_stream_start'
  | 'image_stream_stop'
  | 'raw_command'
  | 'restore';

export interface IHyperionJsonRpcRequest {
  command: string;
  subcommand?: string;
  tan?: number;
  [key: string]: unknown;
}

export interface IHyperionJsonRpcResponse<TInfo = unknown> {
  command?: string;
  subcommand?: string;
  success?: boolean;
  info?: TInfo;
  error?: string;
  errorData?: Array<{ description?: string; [key: string]: unknown }>;
  tan?: number;
  [key: string]: unknown;
}

export interface IHyperionSystemInfo {
  hyperion?: {
    id?: string;
    version?: string;
    build?: string;
    buildType?: string;
    readOnlyMode?: boolean;
    [key: string]: unknown;
  };
  system?: {
    hostName?: string;
    prettyName?: string;
    kernelType?: string;
    productType?: string;
    productVersion?: string;
    [key: string]: unknown;
  };
  [key: string]: unknown;
}

export interface IHyperionComponentState {
  name: THyperionComponentId;
  enabled: boolean;
  [key: string]: unknown;
}

export interface IHyperionEffectDefinition {
  name: string;
  file?: string;
  script?: string;
  args?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IHyperionAdjustment {
  id?: string;
  brightness?: number;
  saturationGain?: number;
  brightnessGain?: number;
  [key: string]: unknown;
}

export interface IHyperionPriority {
  active?: boolean;
  componentId?: string;
  origin?: string;
  owner?: string;
  priority?: number;
  visible?: boolean;
  value?: {
    RGB?: number[];
    HSL?: number[];
    [key: string]: unknown;
  };
  duration_ms?: number;
  [key: string]: unknown;
}

export interface IHyperionInstanceInfo {
  instance: number;
  friendly_name?: string;
  running?: boolean;
  [key: string]: unknown;
}

export interface IHyperionServerInfo {
  hostname?: string;
  activeEffects?: Array<{ name?: string; priority?: number; [key: string]: unknown }>;
  adjustment?: IHyperionAdjustment[];
  components?: IHyperionComponentState[];
  effects?: IHyperionEffectDefinition[];
  instance?: IHyperionInstanceInfo[];
  priorities?: IHyperionPriority[];
  priorities_autoselect?: boolean;
  services?: string[];
  videomode?: string;
  imageToLedMappingType?: string;
  leds?: unknown[];
  [key: string]: unknown;
}

export interface IHyperionImageSnapshot {
  data: string;
  format?: THyperionImageFormat;
  width?: number;
  height?: number;
  contentType?: string;
}

export interface IHyperionRawData {
  sysInfo?: IHyperionSystemInfo;
  serverInfo?: IHyperionServerInfo;
  instanceServerInfo?: Record<number, IHyperionServerInfo>;
  imageSnapshots?: Record<number, IHyperionImageSnapshot>;
  authRequired?: boolean;
  fetchedAt?: string;
}

export interface IHyperionDeviceSnapshotInfo {
  id: string;
  name: string;
  manufacturer: string;
  model?: string;
  version?: string;
  host?: string;
  port?: number;
  jsonPort?: number;
  webPort?: number;
  ssl?: boolean;
  transport?: THyperionTransport;
  hostname?: string;
}

export interface IHyperionInstanceSnapshot {
  instance: number;
  name: string;
  running: boolean;
  serverInfo?: IHyperionServerInfo;
  components: IHyperionComponentState[];
  effects: IHyperionEffectDefinition[];
  effectNames: string[];
  activeEffectNames: string[];
  adjustments: IHyperionAdjustment[];
  priorities: IHyperionPriority[];
  visiblePriority?: IHyperionPriority;
  imageSnapshot?: IHyperionImageSnapshot;
}

export interface IHyperionCapabilities {
  localControl: boolean;
  effects: boolean;
  components: boolean;
  imageSnapshot: boolean;
  liveStreaming: boolean;
  multiInstance: boolean;
  authRequired?: boolean;
}

export interface IHyperionSnapshot {
  device: IHyperionDeviceSnapshotInfo;
  instances: IHyperionInstanceSnapshot[];
  capabilities: IHyperionCapabilities;
  settings: {
    priority: number;
    origin: string;
    effectHideList: string[];
  };
  rawData?: IHyperionRawData;
  online: boolean;
  updatedAt: string;
  source: THyperionSnapshotSource;
  error?: string;
}

export interface IHyperionCommandRequest {
  action: THyperionCommandAction;
  instance?: number | number[];
  priority?: number;
  origin?: string;
  duration?: number;
  color?: number[];
  effect?: string;
  effectArgs?: Record<string, unknown>;
  component?: THyperionComponentId;
  state?: boolean;
  brightness?: number;
  adjustmentId?: string;
  format?: THyperionImageFormat;
  snapshot?: IHyperionSnapshot;
  payload?: IHyperionJsonRpcRequest;
  service?: string;
  target?: Record<string, unknown>;
  data?: Record<string, unknown>;
}

export interface IHyperionCommandExecutor {
  execute(requestArg: IHyperionCommandRequest): Promise<unknown>;
}

export interface IHyperionClientLike {
  getSnapshot?: () => Promise<IHyperionSnapshot | IHyperionRawData>;
  getRawData?: () => Promise<IHyperionRawData>;
  request?: (payloadArg: IHyperionJsonRpcRequest) => Promise<IHyperionJsonRpcResponse>;
  execute?: (requestArg: IHyperionCommandRequest) => Promise<unknown>;
  destroy?: () => Promise<void>;
}

export interface IHyperionConfig {
  host?: string;
  url?: string;
  port?: number;
  jsonPort?: number;
  webPort?: number;
  ssl?: boolean;
  tls?: boolean;
  transport?: THyperionTransport;
  token?: string;
  timeoutMs?: number;
  priority?: number;
  origin?: string;
  effectHideList?: string[];
  instance?: number;
  name?: string;
  manufacturer?: string;
  model?: string;
  uniqueId?: string;
  snapshot?: IHyperionSnapshot;
  rawData?: IHyperionRawData;
  client?: IHyperionClientLike;
  commandExecutor?: IHyperionCommandExecutor;
  online?: boolean;
}

export interface IHomeAssistantHyperionConfig extends IHyperionConfig {}

export interface IHyperionManualEntry extends IHyperionConfig {
  id?: string;
  metadata?: Record<string, unknown>;
}

export interface IHyperionSsdpRecord {
  ssdp_location?: string;
  location?: string;
  ssdp_st?: string;
  st?: string;
  ssdp_usn?: string;
  usn?: string;
  UDN?: string;
  serialNumber?: string;
  friendlyName?: string;
  manufacturer?: string;
  modelName?: string;
  modelNumber?: string;
  server?: string;
  ssdp_server?: string;
  headers?: Record<string, string | string[] | undefined>;
  upnp?: Record<string, unknown>;
  ports?: Record<string, string | number | undefined>;
  metadata?: Record<string, unknown>;
}

export interface IHyperionRefreshResult {
  success: boolean;
  snapshot?: IHyperionSnapshot;
  error?: string;
  data?: unknown;
}
