import type {DefaultTreeAdapterMap} from "parse5";


// Load hook types

export interface RollupHtmlLoadContext {
  node: DefaultTreeAdapterMap['element'];
  sourceId: string;
}



export type AttributeReference = {
  attr: string;
};
export type BodyReference = {
  /**
   * Indiciate this is an inlined reference (node body)
   */
  body: boolean;
  /**
   * Describes what the content type is. I.e 'js' for inlined <script>, 'css' for inlined <style>
   */
  ext?: string;
};

/**
 * Describes how a resource should be loaded.
 */
export type LoadReference = AttributeReference | BodyReference
/**
 * Indicate how to load this resource:
 *  - 'default' uses the default export of the referenced id
 *  - 'chunk'   use the rendered chunk of this file (e.g inlined JS)
 *  - 'entryChunk' mark this resource as its own entry-chunk and use its rendered output path
 *  // TODO: add a type 'asset' here, in which we use rollups emitFile({type:'asset'} feature (which reduces the need for plugin-url, and probably makes more sense as the default option instead of 'default' in zero-config scenarios)
 */
export type LoadType = 'default'|'chunk'|'entryChunk';
export type LoadedReference = (
    {
      // External (virtual) reference
      id: string; // path/url referenced. Or identifier for the virtual source
      source?: string; // Source to use for this id, for inlined chunks
    } | {
      // Inline
      id?: string; // A unique identifier for snippet
      source: string; // Source to use for this id, for inlined chunks
    }
) & {
    type?: LoadType
};

export type LoadResult = undefined|void|false;
export type LoadFunction = (reference: LoadedReference)=>Promise<string>
export type LoadNodeCallback = (loadContext: RollupHtmlLoadContext, load: LoadFunction) => LoadResult|Promise<LoadResult>;


// Make load hook mapping
/**
 * Describes which DOM nodes to extract references from
 */
export type NodeMapping = {
  tagName?: string;
  /** Filter to specific properties to DOM node must have nodes. TODO allowing a callback here probably makes sense */
  match?: ({
    /** Whether the element must have a non-null body */
    body?: boolean
    /** Which additional attributes the element must have to match */
    attr?: {[attrName: string]: (string|RegExp|((value:string)=>boolean))}
  } | ((el: DefaultTreeAdapterMap['element'])=>boolean));

  /**
   * Indicate how to load this resource:
   *  - 'default' uses the default export of the referenced id
   *  - 'chunk'   use the rendered chunk of this file (e.g inlined JS)
   *  - 'entryChunk' mark this resource as its own entry-chunk and use its rendered output path
   */
  loadType?: LoadType
} & LoadReference;
