///////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2002-2026, Open Design Alliance (the "Alliance").
// All rights reserved.
//
// This software and its documentation and related materials are owned by
// the Alliance. The software may only be incorporated into application
// programs owned by members of the Alliance, subject to a signed
// Membership Agreement and Supplemental Software License Agreement with the
// Alliance. The structure and organization of this software are the valuable
// trade secrets of the Alliance and its suppliers. The software is also
// protected by copyright law and international treaty provisions. Application
// programs incorporating this software must include the following statement
// with their copyright notices:
//
//   This application incorporates Open Design Alliance software pursuant to a
//   license agreement with Open Design Alliance.
//   Open Design Alliance Copyright (C) 2002-2026 by Open Design Alliance.
//   All rights reserved.
//
// By use of this software, its documentation or related materials, you
// acknowledge and accept the above terms.
///////////////////////////////////////////////////////////////////////////////

import { Assembly, File, Model } from "@inweb/client";
import { IViewpoint } from "./IViewpoint";

/**
 * The event that fires after each frame in the animation loop.
 *
 * @event
 */
export interface AnimateEvent {
  /**
   * Event type.
   */
  type: "animate";

  /**
   * A {@link https://developer.mozilla.org/docs/Web/API/DOMHighResTimeStamp | DOMHighResTimeStamp}
   * indicating the end time of the previous frame's rendering. See
   * {@link https://developer.mozilla.org/docs/Web/API/Window/requestAnimationFrame | requestAnimationFrame}
   * for more details.
   */
  time: DOMHighResTimeStamp;
}

/**
 * Event that fires when file loading has been canceled.
 *
 * @event
 */
export interface CancelEvent {
  /**
   * Event type.
   */
  type: "cancel";
}

/**
 * Event that fires when the active dragger has been changed.
 *
 * @event
 */
export interface ChangeActiveDraggerEvent {
  /**
   * Event type.
   */
  type: "changeactivedragger";

  /**
   * Dragger name.
   */
  data: string;
}

/**
 * Event that fires when a camera changes.
 */
export interface ChangeCameraEvent {
  /**
   * Event type.
   */
  type: "changecamera";
}

/**
 * Event that fires when camera projection mode changes.
 *
 * @event
 */
export interface ChangeCameraModeEvent {
  /**
   * Event type.
   */
  type: "changecameramode";

  /**
   * New camera mode.
   */
  mode: string;
}

/**
 * Event that fires when cutting planes (slices) have been changed.
 *
 * Fires when cutting planes are added, deleted, or transformed (moved/rotated).
 *
 * @event
 */
export interface ChangeCuttingPlanesEvent {
  /**
   * Event type.
   */
  type: "changecuttingplanes";
}

/**
 * Event that fires when the default color of new markup objects has been changed.
 *
 * @event
 */
export interface ChangeMarkupColorEvent {
  /**
   * Event type.
   */
  type: "changemarkupcolor";

  /**
   * New color.
   */
  data: { r: number; g: number; b: number };
}

/**
 * Event that fires after an open file has been unloaded and the viewer canvas have been cleared.
 *
 * @event
 */
export interface ClearEvent {
  /**
   * Event type.
   */
  type: "clear";
}

/**
 * Event that fires after cutting planes (slices) have been cleared.
 *
 * @event
 */
export interface ClearSlicesEvent {
  /**
   * Event type.
   */
  type: "clearslices";
}

/**
 * Event that fires after markup overlay has been cleared.
 *
 * @event
 */
export interface ClearOverlayEvent {
  /**
   * Event type.
   */
  type: "clearoverlay";
}

/**
 * Event that fires after viewer executes the command.
 *
 * @event
 */
export interface CommandEvent {
  /**
   * Event type.
   */
  type: "command";

  /**
   * Command name.
   */
  data: string;

  /**
   * Command arguments.
   */
  args: any[];
}

/**
 * Event that fires when the file scene description has been loaded.
 *
 * @event
 */
export interface DatabaseChunkEvent {
  /**
   * Event type.
   */
  type: "databasechunk";

  /**
   * Viewer depended data: scene description data (VisualizeJS) or scene object (Three.js).
   */
  data?: any;

  /**
   * File to load.
   */
  file: File | Assembly | Model | string | globalThis.File | ArrayBuffer;

  /**
   * Model from file to load. Only defined when loading a file from the Open Cloud Server.
   */
  model?: Model;
}

/**
 * Event that fires before viewer resources has been released.
 *
 * No more events will be received after the `dispose` event until the viewer is initialized again.
 *
 * @event
 */
export interface DisposeEvent {
  /**
   * Event type.
   */
  type: "dispose";
}

/**
 * Event that fires before viewer resources are released due to canvas removal from DOM.
 *
 * @event
 */
export interface CanvasRemovedEvent {
  /**
   * Event type.
   */
  type: "canvasremoved";
}

/**
 * Event that fires when model breaks into its component objects or collect objects back.
 *
 * @event
 */
export interface ExplodeEvent {
  /**
   * Event type.
   */
  type: "explode";

  /**
   * Explode index. Range is 0 to 100.
   */
  data: number;
}

/**
 * Event that fires when the file geometry data chunk has been loaded.
 *
 * Note that small files are loaded in one chunk, and `geometrychunk` event does not fire, only the
 * `databasechink` event fires.
 *
 * @event
 */
export interface GeometryChunkEvent {
  /**
   * Event type.
   */
  type: "geometrychunk";

  /**
   * Geometry data chunk. Only for VSFX.
   */
  data?: Uint8Array;

  /**
   * File to load.
   */
  file: File | Assembly | Model | string | globalThis.File | ArrayBuffer;

  /**
   * Model from file to load. Only defined when loading a file from the Open Cloud Server.
   */
  model?: Model;
}

/**
 * Event that fires after file has been successfully loaded.
 *
 * @event
 */
export interface GeometryEndEvent {
  /**
   * Event type.
   */
  type: "geometryend";

  /**
   * File to load.
   */
  file: File | Assembly | Model | string | globalThis.File | ArrayBuffer;

  /**
   * Model from file to load. Only defined when loading a file from the Open Cloud Server.
   */
  model?: Model;
}

/**
 * Event that fires when the file fails to load.
 *
 * @event
 */
export interface GeometryErrorEvent {
  /**
   * Event type.
   */
  type: "geometryerror";

  /**
   * Thrown exception.
   */
  data: Error;

  /**
   * File to load.
   */
  file: File | Assembly | Model | string | globalThis.File | ArrayBuffer;

  /**
   * Model from file to load. Only defined when loading a file from the Open Cloud Server.
   */
  model?: Model;
}

/**
 * Event that measures the progress of the file loading.
 *
 * @event
 */
export interface GeometryProgressEvent {
  /**
   * Event type.
   */
  type: "geometryprogress";

  /**
   * The non-rounded progress value from 0 to 1. To get a percentage (%), multiply the `data` by 100.
   */
  data: number;

  /**
   * File to load.
   */
  file: File | Assembly | Model | string | globalThis.File | ArrayBuffer;

  /**
   * Model from file to load. Only defined when loading a file from the Open Cloud Server.
   */
  model?: Model;
}

/**
 * Event that fires before the file loads.
 *
 * @event
 */
export interface GeometryStartEvent {
  /**
   * Event type.
   */
  type: "geometrystart";

  /**
   * File to load.
   */
  file: File | Assembly | Model | string | globalThis.File | ArrayBuffer;

  /**
   * Model from file to load. Only defined when loading a file from the Open Cloud Server.
   */
  model?: Model;
}

/**
 * Event that fires after selected objects becomes invisible.
 *
 * @event
 */
export interface HideEvent {
  /**
   * Event type.
   */
  type: "hide";
}

/**
 * Event that fires after the viewer initialized.
 *
 * @event
 */
export interface InitializeEvent {
  /**
   * Event type.
   */
  type: "initialize";
}

/**
 * Event that measures the progress of the viewer's initialization.
 *
 * @event
 */
export interface InitializeProgressEvent {
  /**
   * Event type.
   */
  type: "initializeprogress";

  /**
   * The non-rounded progress value from 0 to 1. To get a percentage (%), multiply the `data` by 100.
   */
  data: number;

  /**
   * A 64-bit unsigned integer value indicating the amount of work already performed by the underlying
   * process. The ratio of work done can be calculated by dividing total by the value of this property.
   */
  loaded: number;

  /**
   * A 64-bit unsigned integer representing the total amount of work that the underlying process is in
   * the progress of performing.
   */
  total: number;
}

/**
 * Event that fires after selected objects becomes isolated.
 *
 * @event
 */
export interface IsolateEvent {
  /**
   * Event type.
   */
  type: "isolate";
}

/**
 * Event that fires before file open.
 *
 * @event
 */
export interface OpenEvent {
  /**
   * Event type.
   */
  type: "open";

  /**
   * File opening mode.
   */
  mode: string;

  /**
   * File to load.
   */
  file: File | Assembly | Model | string | globalThis.File | ArrayBuffer;
}

/**
 * Event that fires when camera rotating.
 *
 * @event
 */
export interface OrbitEvent {
  /**
   * Event type.
   */
  type: "orbit";
}

/**
 * Event that fires when camera panning.
 *
 * @event
 */
export interface PanEvent {
  /**
   * Event type.
   */
  type: "pan";

  /**
   * The X coordinate of the mouse pointer in screen coordinates.
   */
  x: number;

  /**
   * The Y coordinate of the mouse pointer in screen coordinates.
   */
  y: number;

  /**
   * The X coordinate delta of the mouse pointer relative to the position of the last `Pan` event.
   */
  dX: number;

  /**
   * The Y coordinate delta of the mouse pointer relative to the position of the last `Pan` event.
   */
  dY: number;
}

/**
 * Event that fires when rendering occurs.
 *
 * @event
 */
export interface RenderEvent {
  /**
   * Event type.
   */
  type: "render";

  /**
   * A {@link https://developer.mozilla.org/docs/Web/API/DOMHighResTimeStamp | DOMHighResTimeStamp}
   * indicating the end time of the previous render.
   */
  time: DOMHighResTimeStamp;

  /**
   * The milliseconds passed since the previous render.
   */
  deltaTime: DOMHighResTimeStamp;
}

/**
 * Event that fires when resize occurs.
 *
 * @event
 */
export interface ResizeEvent {
  /**
   * Event type.
   */
  type: "resize";

  /**
   * New width.
   */
  width: number;

  /**
   * New height.
   */
  height: number;
}

/**
 * Event that fires when the selection changes.
 *
 * @event
 */
export interface SelectEvent {
  /**
   * Event type.
   */
  type: "select";

  /**
   * Selection set (viewer dependent).
   */
  data?: any;

  /**
   * Handles of selected objects.
   */
  handles: string[];
}

/**
 * Event that fires after viewer selection changes. Uses model prefix to avoid handle collisions in
 * assemblies (multi-model scenes).
 *
 * @event
 */
export interface Select2Event {
  /**
   * Event type.
   */
  type: "select2";

  /**
   * Selection set (viewer dependent).
   */
  data?: any;

  /**
   * Handles of selected objects with model prefix in format "model:handle".
   */
  handles: string[];
}

/**
 * Event that fires after selected objects becomes visible.
 *
 * @event
 */
export interface ShowEvent {
  /**
   * Event type.
   */
  type: "show";
}

/**
 * Event that fires after all objects becomes visible.
 *
 * @event
 */
export interface ShowAllEvent {
  /**
   * Event type.
   */
  type: "showall";
}

/**
 * Event that fires when an update occurs.
 *
 * @event
 */
export interface UpdateEvent {
  /**
   * Event type.
   */
  type: "update";

  /**
   * `true` to force the update, otherwise the update is delayed until the next animation frame.
   */
  force: boolean;
}

/**
 * Event that fires after viewer loads a viewpoint.
 *
 * @event
 */
export interface ViewpointEvent {
  /**
   * Event type.
   */
  type: "drawviewpoint" | "createviewpoint";

  /**
   * Viewpoint.
   */
  data: IViewpoint;
}

/**
 * Event that fires when walk speed changing.
 *
 * @event
 */
export interface WalkSpeedChangeEvent {
  /**
   * Event type.
   */
  type: "walkspeedchange";

  /**
   * Walk speed multiplier.
   */
  data: number;
}

/**
 * Event that fires when walk started.
 *
 * @event
 */
export interface WalkStartEvent {
  /**
   * Event type.
   */
  type: "walkstart";
}

/**
 * Event that fires when fly speed changing.
 *
 * @event
 */
export interface FlySpeedChangeEvent {
  /**
   * Event type.
   */
  type: "flyspeedchange";

  /**
   * Fly speed multiplier.
   */
  data: number;
}

/**
 * Event that fires when fly started.
 *
 * @event
 */
export interface FlyStartEvent {
  /**
   * Event type.
   */
  type: "flystart";
}

/**
 * Event that fires when zooming to extents or selected objects.
 *
 * @event
 */
export interface ZoomEvent {
  /**
   * Event type.
   */
  type: "zoom";

  /**
   * New view parameters.
   */
  data?: any;
}

/**
 * Event that fires when zooming of the camera using mouse wheel.
 *
 * @event
 */
export interface ZoomAtEvent {
  /**
   * Event type.
   */
  type: "zoomat";

  /**
   * New zoom factor.
   */
  data: number;

  /**
   * X coordinate of the mouse pointer in screen coordinates.
   */
  x: number;

  /**
   * Y coordinate of the mouse pointer in screen coordinates.
   */
  y: number;
}

/**
 * Event that fires when zooming to object.
 *
 * @event
 */
export interface ZoomToEntityEvent {
  /**
   * Event type.
   */
  type: "zoomtoentity";

  /**
   * Object to zoom.
   */
  data: any;
}

/**
 * Viewer Events.
 *
 * @event
 */
export interface ViewerEventMap {
  /**
   * The event that fires after each frame in the animation loop.
   */
  animate: AnimateEvent;

  /**
   * Event that fires when file loading has been canceled.
   */
  cancel: CancelEvent;

  /**
   * Event that fires before viewer resources are released due to canvas removal from DOM.
   */
  canvasremoved: CanvasRemovedEvent;

  /**
   * Event that fires when the active dragger has been changed.
   */
  changeactivedragger: ChangeActiveDraggerEvent;

  /**
   * Event that fires when a camera changes.
   */
  changecamera: ChangeCameraEvent;

  /**
   * Event that fires when camera projection mode changes.
   */
  changecameramode: ChangeCameraModeEvent;

  /**
   * Event that fires when cutting planes (slices) have been changed.
   */
  changecuttingplanes: ChangeCuttingPlanesEvent;

  /**
   * Event that fires when the markup color has been changed.
   */
  changemarkupcolor: ChangeMarkupColorEvent;

  /**
   * Event that fires when the viewer has been cleared.
   */
  clear: ClearEvent;

  /**
   * Event that fires after cutting planes (slices) have been cleared.
   */
  clearslices: ClearSlicesEvent;

  /**
   * Event that fires after markup overlay has been cleared.
   */
  clearoverlay: ClearOverlayEvent;

  /**
   * Event that fires after viewer executes the command.
   */
  command: CommandEvent;

  /**
   * Event that fires after viewer creates a viewpoint.
   */
  createviewpoint: ViewpointEvent;

  /**
   * Event that fires when the file scene description has been loaded.
   */
  databasechunk: DatabaseChunkEvent;

  /**
   * Event that fires before viewer resources has been released.
   */
  dispose: DisposeEvent;

  /**
   * Event that fires after viewer loads a viewpoint.
   */
  drawviewpoint: ViewpointEvent;

  /**
   * Event that fires when model breaks into its component objects or collect objects back.
   */
  explode: ExplodeEvent;

  /**
   * Event that fires when the file geometry data chunk has been loaded.
   */
  geometrychunk: GeometryChunkEvent;

  /**
   * Event that fires after file has been successfully loaded.
   */
  geometryend: GeometryEndEvent;

  /**
   * Event that fires when the file fails to open.
   */
  geometryerror: GeometryErrorEvent;

  /**
   * Event that measures the progress of the file loading.
   */
  geometryprogress: GeometryProgressEvent;

  /**
   * Event that fires before the file opens.
   */
  geometrystart: GeometryStartEvent;

  /**
   * Event that fires after selected objects becomes invisible.
   */
  hide: HideEvent;

  /**
   * Event that fires after the viewer initialized.
   */
  initialize: InitializeEvent;

  /**
   * Event that measures the progress of the viewer's initialization.
   */
  initializeprogress: InitializeProgressEvent;

  /**
   * Event that fires after selected objects becomes isolated.
   */
  isolate: IsolateEvent;

  /**
   * Event that fires before file opens.
   */
  open: OpenEvent;

  /**
   * Event that fires when camera rotating.
   */
  orbit: OrbitEvent;

  /**
   * Event that fires when camera panning.
   */
  pan: PanEvent;

  /**
   * Event that fires when an rendering occurs.
   */
  render: RenderEvent;

  /**
   * Event that fires when resize occurs.
   */
  resize: ResizeEvent;

  /**
   * Event that fires when the selection changes.
   */
  select: SelectEvent;

  /**
   * Event that fires when the selection changes.
   */
  select2: Select2Event;

  /**
   * Event that fires after selected objects becomes visible.
   */
  show: ShowEvent;

  /**
   * Event that fires after all objects becomes visible.
   */
  showall: ShowAllEvent;

  /**
   * Event that fires when an update occurs.
   */
  update: UpdateEvent;

  /**
   * Event that fires when walk speed changing.
   */
  walkspeedchange: WalkSpeedChangeEvent;

  /**
   * Event that fires when walk started.
   */
  walkstart: WalkStartEvent;

  /**
   * Event that fires when fly speed changing.
   */
  flyspeedchange: FlySpeedChangeEvent;

  /**
   * Event that fires when fly started.
   */
  flystart: FlyStartEvent;

  /**
   * Event that fires when zooming to extents or selected objects.
   */
  zoom: ZoomEvent;

  /**
   * Event that fires when zooming of the camera using mouse wheel.
   */
  zoomat: ZoomAtEvent;

  /**
   * Event that fires when zooming to object.
   */
  zoomtoentity: ZoomToEntityEvent;
}
