export interface CanvasDispatcherOptions {}
declare type Renderer = {
  reset(): void;
  renderFrame(width: number, height: number): void | Uint8ClampedArray;
  readPixels(width: number, height: number): Uint8ClampedArray;
  play?(): void;
  pause?(): void;
  dispose?(): void;
};

declare interface RendererConstructor {
  new (data: RenderData): Renderer;
}

declare interface DoneAware {
  onDone(cb: () => void): void;
  isOneShot?: () => boolean; // optional flag
}

declare interface OneShotCapable extends DoneAware {
  resetOneShot(): void;
  signalDoneIfNeeded(): void;
  readonly isOneShotDone: boolean;
}

declare type RendererOptions = "sweep" | "matrix" | "video" | "drop" | "none";

declare type RendererMode =
  | "video"
  | "image"
  | "color"
  | "sequence"
  | "matrix"
  | "text"
  | "overlay";
declare interface RenderSpecification<T extends RendererMode> {
  type: T;
  id: string;
  data: RenderDataSpecification<T>;
  clearOnComplete?: boolean; // Optional: clear canvas when renderer completes (default depends on renderer type)
}

declare interface SourceRenderDataSpecification {
  src: string;
}

declare interface VideoRenderDataSpecification
  extends SourceRenderDataSpecification {
  loop?: boolean | number; // true = infinite, number = specific loop count
  startTime?: number; // optional start time in seconds
  endTime?: number; // optional end time in seconds
}

declare interface ImageRenderDataSpecification
  extends SourceRenderDataSpecification {
  duration?: number; // how long to display in milliseconds
  loop?: boolean | number; // for cycling through multiple images or repeating display
  fadeIn?: number; // optional fade in duration in ms
  fadeOut?: number; // optional fade out duration in ms
  pauseBetweenLoops?: number; // pause duration in milliseconds between loops with blank screen
  colorOverride?: { r: number; g: number; b: number } | string; // For SVGs: override fill colors (RGB object or hex string)
  scroll?: {
    enabled: boolean;
    direction?: "left" | "right" | "up" | "down"; // default: 'left'
    speed?: number; // pixels per second, default: 50
    gap?: number; // gap between image repetitions in pixels, default: 0
    maintainAspectRatio?: boolean; // default: true
    height?: number; // explicit height (width calculated from aspect ratio)
    width?: number; // explicit width (height calculated from aspect ratio)
    offsetX?: number | "center"; // X position (default: 'center' for vertical scroll, 0 for horizontal)
    offsetY?: number | "center"; // Y position (default: 'center' for horizontal scroll, 0 for vertical)
  };
}

declare interface ColorRenderDataSpecification {
  r?: number;
  g?: number;
  b?: number;
  color?: { r: number; g: number; b: number } | string; // RGB object or hex string (alternative to r,g,b)
}

declare interface SequenceRenderDataSpecification {
  patterns: string[]; // Array of pattern IDs to play in sequence
  loop?: boolean | number; // Loop the entire sequence
  transitionDuration?: number; // Optional transition time between patterns in ms
  patternOverrides?: Record<string, any>; // Optional overrides for specific patterns
}

declare interface MatrixRenderDataSpecification {
  speed?: number; // How many pixels each column advances per update (default: 1)
  fallChance?: number; // Probability (0 to 1) that a column will fall on each frame (default: 0.7)
  baseColor?: { r: number; g: number; b: number } | string; // Base RGB color for the matrix effect (RGB object or hex string)
}

declare interface TextRenderDataSpecification {
  text: string; // The text to display (use \n for line breaks)
  fontSize?: number; // Font size in pixels (default: 8, optimized for small LED panels)
  fontFamily?: string; // Font family name (default: monospace font stack for LED readability)
  lineHeight?: number; // Line height in pixels (default: fontSize + 2 for spacing)
  color?: { r: number; g: number; b: number } | string; // Text color (RGB object or hex string, default: white)
  duration?: number; // how long to display in milliseconds (for static text)
  loop?: boolean | number; // for repeating display or scrolling
  pauseBetweenLoops?: number; // pause duration in milliseconds between loops with blank screen
  scroll?: {
    enabled: boolean;
    direction?: "left" | "right" | "up" | "down"; // default: 'left'
    speed?: number; // pixels per second, default: 50
    gap?: number; // gap between text repetitions in pixels, default: 0
    offsetX?: number | "center"; // X position (default: 'center' for vertical scroll, 0 for horizontal)
    offsetY?: number | "center"; // Y position (default: 'center' for horizontal scroll, 0 for vertical)
  };
}

declare type OverlayPosition =
  | "top-left"
  | "top-center"
  | "top-right"
  | "center-left"
  | "center"
  | "center-right"
  | "bottom-left"
  | "bottom-center"
  | "bottom-right";

declare interface OverlayCustomPosition {
  x: number;
  y: number;
}

declare interface OverlayIconConfig {
  src: string; // Image source for the overlay icon
  size: number; // Size of the overlay icon (width and height)
  position: OverlayPosition | OverlayCustomPosition; // Position of the overlay
  offset?: { x?: number; y?: number }; // Optional offset from the position in pixels
  opacity?: number; // Optional opacity (0-1)
  persistent?: boolean; // Whether the overlay should always be visible (default: true)
}

declare interface OverlayRenderDataSpecification {
  baseRenderer: {
    type: string;
    data: any;
  }; // The base renderer configuration
  overlays: OverlayIconConfig[]; // Array of overlay icons to display
  persistOverlaysOnComplete?: boolean; // Whether overlays remain visible after base renderer completes (default: true)
}

declare type RenderDataSpecification<T extends RendererMode> = T extends "video"
  ? VideoRenderDataSpecification
  : T extends "image"
  ? ImageRenderDataSpecification
  : T extends "color"
  ? ColorRenderDataSpecification
  : T extends "sequence"
  ? SequenceRenderDataSpecification
  : T extends "matrix"
  ? MatrixRenderDataSpecification
  : T extends "text"
  ? TextRenderDataSpecification
  : T extends "overlay"
  ? OverlayRenderDataSpecification
  : any;

declare type VideoRenderData = RenderSpecification<"video">;

declare type ImageRenderData = RenderSpecification<"image">;

declare type ColorRenderData = RenderSpecification<"color">;

declare type MatrixRenderData = RenderSpecification<"matrix">;

declare type TextRenderData = RenderSpecification<"text">;

declare type OverlayRenderData = RenderSpecification<"overlay">;

declare type RenderData =
  | VideoRenderData
  | ImageRenderData
  | ColorRenderData
  | MatrixRenderData
  | TextRenderData
  | OverlayRenderData
  | any;

declare interface EndpointData {
  id: string;
  apiPath: string;
  height: number;
  width: number;
  fps: number;
  durationMs?: number | null;
}
