import { Service, EventObject, Machine } from '@zag-js/core';
import { FileMimeType, FileError } from '@zag-js/file-utils';
export { FileError, FileMimeType } from '@zag-js/file-utils';
import { RequiredBy, LocaleProperties, CommonProperties, PropTypes } from '@zag-js/types';

interface FileRejection {
    file: File;
    errors: FileError[];
}
interface FileChangeDetails {
    acceptedFiles: File[];
    rejectedFiles: FileRejection[];
}
interface FileValidateDetails {
    acceptedFiles: File[];
    rejectedFiles: FileRejection[];
}
interface FileAcceptDetails {
    files: File[];
}
interface FileRejectDetails {
    files: FileRejection[];
}

type ElementIds = Partial<{
    root: string;
    dropzone: string;
    hiddenInput: string;
    trigger: string;
    label: string;
    item: (id: string) => string;
    itemName: (id: string) => string;
    itemSizeText: (id: string) => string;
    itemPreview: (id: string) => string;
    itemDeleteTrigger: (id: string) => string;
}>;
interface IntlTranslations {
    dropzone?: string | undefined;
    itemPreview?: ((file: File) => string) | undefined;
    deleteFile?: ((file: File) => string) | undefined;
}
interface FileUploadProps extends LocaleProperties, CommonProperties {
    /**
     * The name of the underlying file input
     */
    name?: string | undefined;
    /**
     * The ids of the elements. Useful for composition.
     */
    ids?: ElementIds | undefined;
    /**
     * The localized messages to use.
     */
    translations?: IntlTranslations | undefined;
    /**
     * The accept file types
     */
    accept?: Record<string, string[]> | FileMimeType | FileMimeType[] | undefined;
    /**
     * Whether the file input is disabled
     */
    disabled?: boolean | undefined;
    /**
     * Whether the file input is required
     */
    required?: boolean | undefined;
    /**
     * Whether to allow drag and drop in the dropzone element
     * @default true
     */
    allowDrop?: boolean | undefined;
    /**
     * The maximum file size in bytes
     *
     * @default Infinity
     */
    maxFileSize?: number | undefined;
    /**
     * The minimum file size in bytes
     *
     * @default 0
     */
    minFileSize?: number | undefined;
    /**
     * The maximum number of files
     * @default 1
     */
    maxFiles?: number | undefined;
    /**
     * Whether to prevent the drop event on the document
     * @default true
     */
    preventDocumentDrop?: boolean | undefined;
    /**
     * Function to validate a file
     */
    validate?: ((file: File, details: FileValidateDetails) => FileError[] | null) | undefined;
    /**
     * The default accepted files when rendered.
     * Use when you don't need to control the accepted files of the input.
     */
    defaultAcceptedFiles?: File[] | undefined;
    /**
     * The controlled accepted files
     */
    acceptedFiles?: File[] | undefined;
    /**
     * Function called when the value changes, whether accepted or rejected
     */
    onFileChange?: ((details: FileChangeDetails) => void) | undefined;
    /**
     * Function called when the file is accepted
     */
    onFileAccept?: ((details: FileAcceptDetails) => void) | undefined;
    /**
     * Function called when the file is rejected
     */
    onFileReject?: ((details: FileRejectDetails) => void) | undefined;
    /**
     * The default camera to use when capturing media
     */
    capture?: "user" | "environment" | undefined;
    /**
     * Whether to accept directories, only works in webkit browsers
     */
    directory?: boolean | undefined;
    /**
     * Whether the file input is invalid
     */
    invalid?: boolean | undefined;
    /**
     * Whether the file input is read-only
     */
    readOnly?: boolean | undefined;
    /**
     * Function to transform the accepted files to apply transformations
     */
    transformFiles?: ((files: File[]) => Promise<File[]>) | undefined;
}
type PropsWithDefault = "minFileSize" | "maxFileSize" | "maxFiles" | "preventDocumentDrop" | "allowDrop" | "translations";
interface Context {
    /**
     * The rejected files
     */
    rejectedFiles: FileRejection[];
    /**
     * The current value of the file input
     */
    acceptedFiles: File[];
    /**
     * Whether files are currently being transformed
     */
    transforming: boolean;
}
type Computed = {
    /**
     * The accept attribute as a string
     */
    acceptAttr: string | undefined;
    /**
     * Whether the file can select multiple files
     */
    multiple: boolean;
};
interface FileUploadSchema {
    state: "idle" | "focused" | "dragging";
    props: RequiredBy<FileUploadProps, PropsWithDefault>;
    context: Context;
    computed: Computed;
    event: EventObject;
    action: string;
    effect: string;
    guard: string;
}
type FileUploadService = Service<FileUploadSchema>;
type FileUploadMachine = Machine<FileUploadSchema>;
type ItemType = "accepted" | "rejected";
interface ItemTypeProps {
    type?: ItemType | undefined;
}
interface ItemProps extends ItemTypeProps {
    file: File;
}
interface ItemPreviewImageProps extends ItemProps {
    url: string;
}
interface ItemGroupProps extends ItemTypeProps {
}
interface DropzoneProps {
    /**
     * Whether to disable the click event on the dropzone
     */
    disableClick?: boolean | undefined;
}
interface FileUploadApi<T extends PropTypes = PropTypes> {
    /**
     * Whether the user is dragging something over the root element
     */
    dragging: boolean;
    /**
     * Whether the user is focused on the dropzone element
     */
    focused: boolean;
    /**
     * Whether the file input is disabled
     */
    disabled: boolean;
    /**
     * Whether the file input is in read-only mode
     */
    readOnly: boolean;
    /**
     * Whether files are currently being transformed via `transformFiles`
     */
    transforming: boolean;
    /**
     * Whether the maximum number of files has been reached
     */
    maxFilesReached: boolean;
    /**
     * The number of files that can still be added
     */
    remainingFiles: number;
    /**
     * Function to open the file dialog
     */
    openFilePicker: VoidFunction;
    /**
     * Function to delete the file from the list
     */
    deleteFile: (file: File, type?: ItemType | undefined) => void;
    /**
     * The accepted files that have been dropped or selected
     */
    acceptedFiles: File[];
    /**
     * The files that have been rejected
     */
    rejectedFiles: FileRejection[];
    /**
     * Sets the accepted files
     */
    setFiles: (files: File[]) => void;
    /**
     * Clears the accepted files
     */
    clearFiles: VoidFunction;
    /**
     * Clears the rejected files
     */
    clearRejectedFiles: VoidFunction;
    /**
     * Returns the formatted file size (e.g. 1.2MB)
     */
    getFileSize: (file: File) => string;
    /**
     * Returns the preview url of a file.
     * Returns a function to revoke the url.
     */
    createFileUrl: (file: File, cb: (url: string) => void) => VoidFunction;
    /**
     * Sets the clipboard files
     * Returns `true` if the clipboard data contains files, `false` otherwise.
     */
    setClipboardFiles: (dt: DataTransfer | null) => boolean;
    getLabelProps: () => T["label"];
    getRootProps: () => T["element"];
    getDropzoneProps: (props?: DropzoneProps) => T["element"];
    getTriggerProps: () => T["button"];
    getHiddenInputProps: () => T["input"];
    getItemGroupProps: (props?: ItemGroupProps) => T["element"];
    getItemProps: (props: ItemProps) => T["element"];
    getItemNameProps: (props: ItemProps) => T["element"];
    getItemPreviewProps: (props: ItemProps) => T["element"];
    getItemPreviewImageProps: (props: ItemPreviewImageProps) => T["img"];
    getItemSizeTextProps: (props: ItemProps) => T["element"];
    getItemDeleteTriggerProps: (props: ItemProps) => T["button"];
    getClearTriggerProps: () => T["button"];
}

export type { DropzoneProps, ElementIds, FileAcceptDetails, FileChangeDetails, FileRejectDetails, FileRejection, FileUploadApi, FileUploadMachine, FileUploadProps, FileUploadSchema, FileUploadService, FileValidateDetails, IntlTranslations, ItemGroupProps, ItemPreviewImageProps, ItemProps, ItemType, ItemTypeProps };
