interface XmanItem<T> {
  id: string;
  data: T;
  createTime: string;
  updateTime: string;
  version: number;
}

interface XmanItemsList<T> {
  items: XmanItem<T>[];
  /** 
   * Use in the next `list<T>()` call to get the next set of results.
   * No more pages left if `nextPageToken` is not present.
  */
  nextPageToken?: string;
}

/**
 * Options for reading a list
 */

interface ListParams {
  /** in page size. Default 12. Max 24. */
  pageSize?: number;
  /** `nextPageToken` returned by the previous `list()` call. */
  nextPage?: string;
  /** property path to order by, followed by direction. E.g. `name asc` */
  orderBy?: string;
}

type XMValidValues = number | string | Date | number[] | string[] | boolean
type XmanProperties = Record<string, XMValidValues | XmanProperties>
interface DecisionInputs {
  anonymousId?: string
  userId?: string
  properties?: XmanProperties
}
interface MockContext {
  profile?: XmanProperties
  events?: {
    eventName: string
    at: number
    payload?: XmanProperties
  }[]
  requestContext?: XmanProperties
  serverContext?: XmanProperties
}
declare namespace XmanFieldValue {
  interface Reference {
    collection: string;
    id: string;
    /** Label is cached at the time reference is created. Not updated with the item changes. */
    label?: string;
    altText?: string;
    thumbId?: string;
  }

  interface File {
    contentType: string,
    name: string,
    storageName: string,
    md5Hash: string,
    size: number,
    publicUrl: string
  }

  interface Place {
    rawAddress?: string,
    streetAddress?: string,
    unit?: string,
    city?: string,
    state?: string,
    postal_code?: string,
    country?: string,
    neighborhood?: string,
    latitude: number,
    longitude: number,
    geohashes?: string[],
    geohash?: {
      p_1: string,
      p_2: string,
      p_3: string,
      p_4: string,
      p_5: string,
      p_6: string,
      p_7: string,
      p_8: string,
      p_9: string,
      p_10: string,
      p_11: string,
      p_12: string,
    },
    google_place?: {
      neighborhood: string,
      administrative_area_level_1: string,
      route: string,
      postal_code: string,
      locality: string,
      country: string,
      street_number: string,
      subpremise: string,
      latitude: number,
      longitude: number
    },
  }
}

interface ImageSettings {
  /**
   * Key to identify the variation of the image.
   * `getImage(s)` will return variations in a map keyed by this key
   * */
  key: string;
  /** Image width. If larger than actual image width, actual width is used */
  width?: number;
  /** Image height. If larger than actual image height, actual height is used */
  height?: number;
  fit?: 'cover' | 'fill' | 'contain';
}

interface HTMLImageData {
  alt: string;
  variations: {
    [key: string]: {
      src: string;
      width?: number;
      height?: number;
    };
  };
}
interface MoadeDecisionResult {
  promo: {
    payload: {
      id: string
      title?: string
      cta?: string
      targetUrl?: string
      name?: string
      coverImage?: XmanFieldValue.Reference[]
    }
    goalEventName?: string
  }
}

interface EventPayload {
  event?: string
  userId?: string
  anonymousId?: string
  properties?: XmanProperties
}

interface AnalyticsInstance {
  getState: () => {
    context?: {
      campaign?: XmanProperties
    }
  }
}

type TrackerFunction = ({ payload, instance }: { payload: EventPayload, instance: AnalyticsInstance }) => void

type ProxyResult<T> = {
    success: true;
    data: T;
} | {
    success: false;
    response: Response;
};

interface AnalyticsPlugin {
    name: string;
    initialize?: TrackerFunction;
    track?: TrackerFunction;
    page?: TrackerFunction;
    identify?: TrackerFunction;
}
interface WorkspaceWrapper {
    /**
     * Reads a specific item. *Returns `null` if item is not found*
     * @param {string} collection collection ID (e.g. xman-articles)
     * @param {string} itemId 20 character Item ID (e.g. dXEFNfms7zlMI8AdbFND)
     * @returns {Promise<XmanItem<T> | null>} an item or `null`
     */
    read<T>(collection: string, itemId: string): Promise<XmanItem<T> | null>;
    /**
     * Loads and returns the first referenced item in the reference list. If the list is empty, returns null
     *
     * @param referenceFieldValue {XmanFieldValue.Reference[]} field value of a reference field. Use directly from the response of previous calls
     * @returns {Promise<XmanItem<T> | null>} First referenced item or `null` if no items referenced
     */
    readReferencedItem<T>(referenceFieldValue?: XmanFieldValue.Reference[]): Promise<XmanItem<T> | null>;
    /**
     * Loads and returns all the referenced items in the reference list. If the list is empty, returns [].
     * This method ignores all items that fail to load. E.g. The API Client you created may not have access to some collections
     * If you want the call to fail when such errors happen, pass `failOnPartialFailure = true`
     *
     * @param referenceFieldValue {XmanFieldValue.Reference[]} field value of a reference field. Use directly from the response of previous calls
     * @param failOnPartialFailure {boolean} if `true` throws an error if any item reference throws an error
     * @returns {[Promise<XmanItem<T>]} First referenced item or `null` if no items referenced
     * @throws Error when `failOnPartialFailure = true` and one or more items fail to load
     */
    readReferencedItems<T>(referenceFieldValue?: XmanFieldValue.Reference[], failOnPartialFailure?: boolean): Promise<XmanItem<T>[]>;
    /**
     * Read a list of items. Simple paging and sorting is supported.
     *
     * Use `query()` for more sophisticated queries
     *
     * @param {string} collection
     * @param {ListParams?} listParams Parameters for the list
     */
    list<T>(collection: string, listParams?: ListParams): Promise<XmanItemsList<T>>;
    /**
     * Call the MOADE.ai to get a decision.
     *
     * Make sure you retrieve the userId and anonymousId from your Analytics implementation
     * and pass it in decisionInputs
     *
     * @param {string} decisionFlowId Flat Decision Flow Id. Get from the MOADE test harness
     * @param {DecisionInputs} decisionInputs Parameters for making the decision
     * @param {MockContext?} mockContext optional mock context. Use only for testing
     *
     */
    decide(decisionFlowId: string, decisionInputs: DecisionInputs, mockContext?: MockContext): Promise<ProxyResult<MoadeDecisionResult>>;
    /**
     * Returns a plugin to be used with the analytics.js library or Segment
     *
     */
    getMoadeAnalyticsPlugin(): AnalyticsPlugin;
    /**
     * Generates alt text and image URLs for a set of image references.
     *
     * @param {XmanFieldValue.Reference[]} imgRefs pointers to image items. You can use the reference field values directly
     * @param {ImageSettings?} imageSettings image settings
     * @returns Promise<HTMLImageData[]> list of image details
     */
    getImages(imgRefs: XmanFieldValue.Reference[], imageSettings?: ImageSettings[]): Promise<HTMLImageData[]>;
    /**
     * Generates alt text and image URLs for one image reference
     *
     * @param {XmanFieldValue.Reference} imgRef pointers to an image item. You can use the reference field value directly
     * @param {ImageSettings?} imageSettings image settings
     * @returns Promise<HTMLImageData> image details
     */
    getImage(imgRef: XmanFieldValue.Reference, imageSettings?: ImageSettings[]): Promise<HTMLImageData>;
    /**
     * Generates image URLs for one image reference.
     * Use with references in Live Collections where the Alt in the is always up-to-date.
     * *NOTE* that this is a synchronous function. Don't await.
     *
     * @param {XmanFieldValue.Reference} imgRef pointers to an image item. You can use the reference field value directly
     * @param {ImageSettings?} imageSettings image settings
     * @returns HTMLImageData['variations'] image details
     */
    generateImageVariations(imgRef: XmanFieldValue.Reference, imageSettings?: ImageSettings[]): HTMLImageData['variations'];
    /**
     * Change the stage to pull data from. Default is 'live'
     * @param {String} stageName
     */
    stage(stageName: string): WorkspaceWrapper;
    /**
     * Point to a separate delivery CDN.
     * Only applicable to "Environment" plans.
     *
     * @param {String} cdnServer CDN Server URL
     */
    cdn(cdnServer: string): WorkspaceWrapper;
    /**
     * Point to a separate MOADE.ai decision server.
     * Only applicable to "Environment" plans.
     *
     * @param {String} moadeServer MOADE.ai Server URL
     */
    moade(moadeServer: string): WorkspaceWrapper;
    /**
     * Provide the secret part of the key for server side access without `Origin` check
     * *DO NOT USE IN A CLIENT SIDE WEB APP*
     * Please use in server only settings for SSR apps such as NuxtJS, NextJS, Gatsby, etc.
     *
     * @param {String} secret for server side access.
     */
    secret(secret: string): WorkspaceWrapper;
}
/**
 *
 * @param clientId API client ID from XMan I/O
 * @param workspaceId Workspace ID. You can see this in the URL on XMan I/O
 * @param stageName 'live' by default
 * @param cdnServer Ignore. Unless Liquiron support has asked you to set this
 * @param moadeServer Ignore. Unless Liquiron support has asked you to set this
 * @param secret Secret for server side access. DO NOT USE IN THE BROWSER
 * @returns Workspace object
 */
declare const getWorkspace: (clientId: string, workspaceId: string, stageName?: string, cdnServer?: string, moadeServer?: string, secret?: string) => WorkspaceWrapper;

export { XmanFieldValue, getWorkspace };
export type { AnalyticsPlugin, DecisionInputs, HTMLImageData, ImageSettings, ListParams, MoadeDecisionResult, MockContext, WorkspaceWrapper, XMValidValues, XmanItem, XmanItemsList, XmanProperties };
