/// <reference types="astro/astro-jsx" />

import type { ImageUrlBuilder } from "@sanity/image-url/lib/types/builder";
import type {
  ImageUrlBuilderOptionsWithAliases,
  SanityImageDimensions,
  SanityImageSource,
  SanityImageWithAssetStub,
} from "@sanity/image-url/lib/types/types";

/**
 * Default properties for all components in the app
 */
export interface SanityPictureDefaults {
  autoWidths: AutoWidths;
  withWebp: boolean;
  style: Record<string, any>;
  img: Omit<ImgAttributes, "src">;
  lqip: Lqip;
  imageUrlBuilder?: ImageUrlBuilder;
}

/**
 * Settings for auto-generating the widths of our element
 */
export interface AutoWidths {
  //The highest width image to generate when dimensions are not provided
  maxWidth: number;
  //The width to jump by each source, unless we would exceed maxDivisions
  step: number;
}

/**
 * Settings for using low quality placeholder image
 */
export type Lqip =
  | {
      enabled: false;
    }
  | {
      enabled: true;
      //Transition to loaded image time in ms
      transitionDuration: number;
    };

/**
 * An image asset from sanity which has fetched dimension metadata
 */
export type SanityDimensionedImage = SanityImageWithAssetStub & {
  asset: {
    metadata: { dimensions: SanityImageDimensions };
  };
};

/**
 * An image asset from sanity which has fetched dimension metadata
 */
export type SanityImageWithLqip = SanityImageWithAssetStub & {
  asset: {
    metadata: { lqip: string };
  };
};

/**
 * Type for our component's props
 */
export type SanityPictureProps = {
  /**
   * An instance of sanity image url builder to use. If default is set, may be omitted
   */
  imageUrlBuilder?: ImageUrlBuilder;
  /**
   * The image to display, as a property from a `groq` query
   */
  src: SanityImageSource;
  /**
   * Specifies sizes attribute to apply to each source by default
   */
  sizes: string;
  /**
   * Each `PictureSource` object in the list informs the generation of a `<source />` element for each of the widths generated by the `widths` property.
   */
  sources?: PictureSource[];
  /**
   * Specifies how to calculate widths for `<source />` elements. You may either specify a list of widths to use, or a an `AutoWidths` type which declares how to automatically determine the widths.
   */
  widths?: number[] | AutoWidths;
  /**
   * Attributes to apply to the base `<img />` element in the picture
   */
  img?: Omit<ImgAttributes, "src">;
  lqip?: Lqip;
  loading?: ImgAttributes["loading"];
} & PictureAttributes;

/**
 * Options for a single <source /> in a <picture />
 */
export type PictureSource = {
  options?: Partial<ImageUrlBuilderOptionsWithAliases>;
  withWebp?: boolean;
} & Omit<SourceAttributes, "srcset">;

export type SourceAttributes = astroHTML.JSX.DefinedIntrinsicElements["source"];
export type PictureAttributes =
  astroHTML.JSX.DefinedIntrinsicElements["picture"];
export type ImgAttributes = astroHTML.JSX.DefinedIntrinsicElements["img"];

declare global {
  var sanityPictureDefaults: SanityPictureDefaults;
}
