///////////////////////////////////////////////////////////////////////////////
// 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 type { Assembly, File, Model } from "@inweb/client";
import type { IViewer } from "../viewer/IViewer";

/**
 * Defines the file source to load into the viewer:
 *
 * - `File`, `Assembly`, or `Model` instance from the Open Cloud Server
 * - `URL` string
 * - {@link https://developer.mozilla.org/docs/Web/HTTP/Basics_of_HTTP/Data_URIs | Data URL} string
 * - {@link https://developer.mozilla.org/docs/Web/API/File | Web API File} object
 * - {@link https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer | ArrayBuffer}
 *   object
 */
export type FileSource = File | Assembly | Model | string | globalThis.File | ArrayBuffer;

/**
 * Defines the file loading parameters (loader depended).
 */
export type LoadParams = {
  [key: string | number | symbol]: any;
};

/**
 * Defines the file loader for the viewer.
 */
export interface ILoader {
  /**
   * The name of the loader.
   */
  name?: string;

  /**
   * Releases resources allocated by the loader.
   */
  dispose(): void;

  /**
   * Returns `true` if the specified file can be loaded by this loader.
   *
   * @param file - File to load.
   * @param format - File format string.
   */
  isSupport(file: FileSource, format?: string): boolean;

  /**
   * Loads a file into the viewer.
   *
   * @param file - File to load.
   * @param format - File format string.
   * @param params - Loading parameters.
   */
  load(file: FileSource, format?: string, params?: LoadParams): Promise<this>;

  /**
   * Cancels asynchronous loading started with {@link load | load()}.
   */
  cancel(): void;

  /**
   * Yields control back to the browser's event loop, allowing UI updates and other pending tasks to
   * execute. This method is used during long-running loading operations to prevent the browser from
   * becoming unresponsive.
   */
  yield(): Promise<void>;
}

/**
 * Defines the loader provider function.
 */
export interface ILoaderProvider {
  /**
   * @param viewer - Viewer instance that creates the loader.
   */
  (viewer: any): ILoader;
}

/**
 * Defines the viewer loaders registry interface.
 */
export interface ILoadersRegistry {
  /**
   * Binds a loader name to a loader. Registering a loader with an existing name twice overrides the
   * existing loader.
   *
   * @param name - Unique name for the loader.
   * @param provider - Loader provider.
   */
  registerLoader(name: string, provider: ILoaderProvider): void;

  /**
   * Returns a list of registered loaders.
   */
  getLoaders(): Map<string, ILoaderProvider>;

  /**
   * Creates the loader of the specified file. Returns `null` if the file format is not supported.
   *
   * @param viewer - Viewer instance that wants to create the loader.
   */
  createLoader(viewer: IViewer, file: FileSource, format?: string): ILoader | null;
}
