declare module "glightbox" {
  export type SLIDE_DESC_POSITION_TOP = "top";
  export type SLIDE_DESC_POSITION_BOTTOM = "bottom";
  export type SLIDE_DESC_POSITION_LEFT = "left";
  export type SLIDE_DESC_POSITION_RIGHT = "right";
  export type SlideDescPositions = SLIDE_DESC_POSITION_TOP | SLIDE_DESC_POSITION_BOTTOM | SLIDE_DESC_POSITION_LEFT | SLIDE_DESC_POSITION_RIGHT;

  export type SLIDE_TYPE_IMAGE = "image";
  export type SLIDE_TYPE_VIDEO = "video";
  export type SLIDE_TYPE_INLINE = "inline";
  export type SlideTypes = SLIDE_TYPE_IMAGE | SLIDE_TYPE_VIDEO | SLIDE_TYPE_INLINE;

  export type VIDEO_SOURCE_VIMEO = "vimeo";
  export type VIDEO_SOURCE_YOUTUBE = "youtube";
  export type VIDEO_SOURCE_LOCAL = "local";
  export type VideoSources = VIDEO_SOURCE_VIMEO | VIDEO_SOURCE_YOUTUBE | VIDEO_SOURCE_LOCAL;

  export type EFFECT_FADE = "fade";
  export type EFFECT_ZOOM = "zoom";
  export type EFFECT_SLIDE = "slide";
  export type EFFECT_NONE = "none";
  export type SlideEffects = EFFECT_FADE | EFFECT_ZOOM | EFFECT_SLIDE | EFFECT_NONE;
  export type OpenCloseEffects = EFFECT_FADE | EFFECT_ZOOM | EFFECT_NONE;

  export interface SlideOptions {
    /**
     * Content link - image or video
     */
    href?: string;

    /**
     * Content of slide (when href not specified)
     * @example 
     * ```
     *  {
          'content': '<p>This will append some html inside the slide</p>' // read more in the API section
        }
        ```
     */
    content?: string | HTMLElement | false;

    /**
     * Slide title
     */
    title?: string;

    /**
     * Slide alternative text
     */
    alt?: string;

    /**
     * Slide descriptione
     */
    description?: string;

    /**
     * Position of description
     */
    descPosition?: SlideDescPositions;

    /**
     * Type of slide.
     *
     * Type is only required if GLightbox fails to know what kind of content should display
     */
    type?: SlideTypes;

    /**
     * Video source
     */
    source?: VideoSources;

    /**
     * Slide effect
     */
    effect?: SlideEffects;

    /**
     * Width of slide
     * 
     * @example 
     * ```
      {
          width: "900px",
      }
     * ```
     *
     * @example 
     * ```
      {
          width: 900,
      }
     * ```
     */
    width?: string | number;

    /**
     * Height of slide
     * 
     * @example 
     * ```
      {
          height: "100vh",
      }
     * ```
     *
     * @example 
     * ```
      {
          height: 50,
      }
     * ```
     */
    height?: string | number;

    /**
     * Slide is zoomable
     */
    zoomable?: boolean;

    /**
     * Slide is draggable
     */
    draggable?: boolean;

    /**
     * Image sizes
     */
    sizes?: string;

    /**
     * Image srcset
     */
    srcset?: string;
  }

  export type Player = any;

  export interface SlideData {
    /**
     * The index of slide
     */
    slideIndex: number;

    /**
     * The node you can modify
     */
    slideNode: Node;

    /**
     * Contains the configuration of the slide like title, description, etc.
     */
    slideConfig: SlideOptions;

    /**
     * The slide player if it exists otherwise will return false
     */
    player: Player | false;

    /**
     * Contains the element that triggers this slide, this can be a link, a button, etc in your HTML, it can be null if the elements in the gallery were set dynamically
     */
    trigger: HTMLElement | null;
  }

  export interface SlideChangeData {
    /**
     * Previous slide
     */
    prev: SlideData;

    /**
     * Current slide
     */
    current: SlideData;
  }

  export type HOOK_OPENED = "open";
  export type HOOK_CLOSED = "close";
  export type HOOK_BEFORE_SLIDE_CHANGED = "slide_before_change";
  export type HOOK_SLIDE_CHANGED = "slide_changed";
  export type HOOK_BEFORE_SLIDE_LOADED = "slide_before_load";
  export type HOOK_AFTER_SLIDE_LOADED = "slide_after_load";
  export type HOOK_SLIDE_INSERTED = "slide_inserted";
  export type HOOK_SLIDE_REMOVED = "slide_removed";

  export type GLightboxHooks =
    | HOOK_OPENED
    | HOOK_CLOSED
    | HOOK_BEFORE_SLIDE_CHANGED
    | HOOK_SLIDE_CHANGED
    | HOOK_BEFORE_SLIDE_LOADED
    | HOOK_AFTER_SLIDE_LOADED
    | HOOK_SLIDE_INSERTED
    | HOOK_SLIDE_REMOVED;

  export type OpenEvent = () => void;
  export type CloseEvent = () => void;
  export type BeforeSlideChangedEvent = (props: SlideChangeData) => void;
  export type SlideChangedEvent = (props: SlideChangeData) => void;
  export type SlideBeforeLoadEvent = (data: SlideData) => void;
  export type SlideAfterLoadEvent = (data: SlideData) => void;
  export type SlideInsertedEvent = (data: SlideData) => void;
  export type SlideRemovedEvent = (index: number) => void;

  export type HookCallback<T extends GLightboxHooks> = T extends HOOK_OPENED
    ? OpenEvent
    : T extends HOOK_CLOSED
    ? CloseEvent
    : T extends HOOK_BEFORE_SLIDE_CHANGED
    ? BeforeSlideChangedEvent
    : T extends HOOK_SLIDE_CHANGED
    ? SlideChangedEvent
    : T extends HOOK_BEFORE_SLIDE_LOADED
    ? SlideBeforeLoadEvent
    : T extends HOOK_AFTER_SLIDE_LOADED
    ? SlideAfterLoadEvent
    : T extends HOOK_SLIDE_INSERTED
    ? SlideInsertedEvent
    : T extends HOOK_SLIDE_REMOVED
    ? SlideRemovedEvent
    : never;

  export interface GLighboxOptions {
    /**
     * Name of the selector for example '.glightbox' or 'data-glightbox' or '*[data-glightbox]'
     * @defaultValue ".glightbox"
     */
    selector?: string;

    /**
     * Instead of passing a selector you can pass all the items that you want in the gallery.
     *
     * @defaultValue null
     */
    elements?: SlideOptions[];
    /**
     * Name of the skin, it will add a class to the lightbox so you can style it with css.
     *
     * @defaultValue clean
     */
    skin?: string;

    /**
     * 	Name of the effect on lightbox open. (zoom, fade, none)
     *
     * @defaultValue zoom
     */
    openEffect?: OpenCloseEffects;

    /**
     * Name of the effect on lightbox close. (zoom, fade, none)
     *
     * @defaultValue zoom
     */
    closeEffect?: OpenCloseEffects;

    /**
     * Name of the effect on slide change. (slide, fade, zoom, none)
     *
     * @defaultValue slide
     */
    slideEffect?: SlideEffects;

    /**
     * More text for descriptions on mobile devices.
     *
     * @defaultValue "See more"
     */
    moreText?: string;

    /**
     * Number of characters to display on the description before adding the moreText link (only for mobiles), if 0 it will display the entire description.
     *
     * @defaultValue 60
     */
    moreLength?: number;

    /**
     * Show or hide the close button.
     *
     * @defaultValue true
     */
    closeButton?: boolean;

    /**
     * Enable or disable the touch navigation (swipe).
     *
     * @defaultValue true
     */
    touchNavigation?: boolean;

    /**
     * Image follow axis when dragging on mobile.
     *
     * @defaultValue true
     */
    touchFollowAxis?: boolean;

    /**
     * Enable or disable the keyboard navigation.
     *
     * @defaultValue true
     */
    keyboardNavigation?: boolean;

    /**
     * Close the lightbox when clicking outside the active slide.
     *
     * @defaultValue true
     */
    closeOnOutsideClick?: boolean;

    /**
     * Start lightbox at defined index.
     *
     * @defaultValue 0
     */
    startAt?: number;

    /**
     * Default width for inline elements and iframes, you can define a specific size on each slide. You can use any unit for example 90% or 100vw for full width
     *
     * @defaultValue 900px
     */
    width?: string | number;

    /**
     * Default height for inline elements and iframes, you can define a specific size on each slide.You can use any unit for example 90% or 100vh For inline elements you can set the height to auto.
     *
     * @defaultValue 506px
     */
    height?: string | number;

    /**
     * Default width for videos. Videos are responsive so height is not required. The width can be in px % or even vw for example, 500px, 90% or 100vw for full width videos
     *
     * @defaultValue 960px
     */
    videosWidth?: string | number;

    /**
     * Global position for slides description, you can define a specific position on each slide (bottom, top, left, right).
     *
     * @defaultValue bottom
     */
    descPosition?: SlideDescPositions;

    /**
     * Loop slides on end.
     *
     * @defaultValue false
     */
    loop?: boolean;

    /**
     * Enable or disable zoomable images you can also use data-zoomable="false" on individual nodes.
     *
     * @defaultValue true
     */
    zoomable?: boolean;

    /**
     * Enable or disable mouse drag to go prev and next slide (only images and inline content), you can also use data-draggable="false" on individual nodes.
     *
     * @defaultValue true
     */
    draggable?: boolean;

    /**
     * Used with draggable. Number of pixels the user has to drag to go to prev or next slide.
     *
     * @defaultValue 40
     */
    dragToleranceX?: number;

    /**
     * Used with draggable. Number of pixels the user has to drag up or down to close the lightbox (Set 0 to disable vertical drag).
     *
     * @defaultValue 65
     */
    dragToleranceY?: number;

    /**
     * If true the slide will automatically change to prev/next or close if dragToleranceX or dragToleranceY is reached, otherwise it will wait till the mouse is released.
     *
     * @defaultValue false
     */
    dragAutoSnap?: boolean;

    /**
     * Enable or disable preloading.
     *
     * @defaultValue true
     */
    preload?: boolean;

    /**
     * Set your own svg icons.
     *
     * @defaultValue {}
     */
    svg?: object;

    /**
     * Define or adjust lightbox animations.
     * @see https://github.com/biati-digital/glightbox#animations
     */
    cssEfects?: object;

    /**
     * You can completely change the html of GLightbox.
     * @see https://github.com/biati-digital/glightbox#themeable
     */
    lightboxHTML?: string;

    /**
     * You can completely change the html of the individual slide.
     * @see https://github.com/biati-digital/glightbox#themeable
     */
    slideHTML?: string;

    /**
     * Autoplay videos on open.
     *
     * @defaultValue true
     */
    autoplayVideos?: boolean;

    /**
     * If true video will be focused on play to allow keyboard sortcuts for the player, this will deactivate prev and next arrows to change slide so use it only if you know what you are doing.
     *
     * @defaultValue false
     */
    autofocusVideos?: boolean;

    /**
     * View video player options.
     *
     * @see https://github.com/biati-digital/glightbox#video-player
     * @defaultValue {}
     */
    plyr?: object;
  }

  export type GLighboxInstance = {
    /**
     * Open the lightbox, you can optionally pass a node.
     */
    open: (node?: Node) => void;

    /**
     * Open at specific index.
     */
    openAt: (index: number) => void;

    /**
     * Close the lightbox.
     */
    close: () => void;

    /**
     * Reload the lightbox, after inserting content with ajax.
     */
    reload: () => void;

    /**
     * Destroy and remove all attached events.
     */
    destroy: () => void;

    /**
     * Go to previous slide.
     */
    prevSlide: () => void;

    /**
     * Go to next slide.
     */
    nextSlide: () => void;

    /**
     * Go to specific slide
     */
    goToSlide: (index: number) => void;

    /**
     * Insert a slide at the specified index.
     */
    insertSlide: (slide: SlideOptions, index: number) => void;

    /**
     * Remove slide at the specified index.
     */
    removeSlide: (index: number) => void;

    /**
     * Get active slide. It will return the active node.
     */
    getActiveSlide: () => Node;

    /**
     * Get active slide. It will return the active slide index.
     */
    getActiveSlideIndex: () => number;

    /**
     * Play video in the specified slide.
     */
    slidePlayerPlay: (index: number) => void;

    /**
     * Pause video in the specified slide.
     */
    slidePlayerPause: (index: number) => void;

    /**
     * Get the player instance of the specified slide.
     */
    getSlidePlayerInstance: (node: Node, index: number) => Player;

    /**
     * Get all players instance.
     */
    getAllPlayers: () => Player[];

    /**
     * 	Update the lightbox gallery elements.
     */
    setElements: (slides: SlideOptions[]) => void;

    /**
     * Set an event listener
     */
    on: <T extends GLightboxHooks>(event: T, callback: HookCallback<T>) => void;

    /**
     * Set an event listener that will be triggered only once.
     */
    once: <T extends GLightboxHooks>(event: T, callback: HookCallback<T>) => void;
  };

  export default function GLightbox(options: GLighboxOptions): GLighboxInstance;
}
