import koffi from 'koffi';

/**
 * Get the library, setting it up if needed
 */
declare const getFfi: () => {
    CameraList: koffi.IKoffiCType;
    Camera: koffi.IKoffiCType;
    CameraAbilitiesList: koffi.IKoffiCType;
    CameraAbilities: koffi.IKoffiCType;
    CameraText: koffi.IKoffiCType;
    GPPortInfoList: koffi.IKoffiCType;
    GPPortInfo: koffi.IKoffiCType;
    CameraEventType: koffi.IKoffiCType;
    CameraFileType: koffi.IKoffiCType;
    CameraFilePath: koffi.IKoffiCType;
    CameraFile: koffi.IKoffiCType;
    CameraWidget: koffi.IKoffiCType;
    CameraWidgetType: koffi.IKoffiCType;
    GPContextIdleFunc: koffi.IKoffiCType;
    GPContextProgressStartFunc: koffi.IKoffiCType;
    GPContextProgressUpdateFunc: koffi.IKoffiCType;
    GPContextProgressStopFunc: koffi.IKoffiCType;
    GPContextErrorFunc: koffi.IKoffiCType;
    GPContextQuestionFunc: koffi.IKoffiCType;
    GPContextCancelFunc: koffi.IKoffiCType;
    GPContextStatusFunc: koffi.IKoffiCType;
    GPContextMessageFunc: koffi.IKoffiCType;
    GPContext: koffi.IKoffiCType;
} & {
    gp_abilities_list_new: (...args: unknown[]) => Promise<number>;
    gp_abilities_list_load: (...args: unknown[]) => Promise<number>;
    gp_abilities_list_lookup_model: (...args: unknown[]) => Promise<number>;
    gp_abilities_list_get_abilities: (...args: unknown[]) => Promise<number>;
    gp_abilities_list_free: (...args: unknown[]) => Promise<number>;
    gp_port_info_list_new: (...args: unknown[]) => Promise<number>;
    gp_port_info_list_load: (...args: unknown[]) => Promise<number>;
    gp_port_info_list_lookup_path: (...args: unknown[]) => Promise<number>;
    gp_port_info_list_get_info: (...args: unknown[]) => Promise<number>;
    gp_port_info_list_free: (...args: unknown[]) => Promise<number>;
    gp_context_new: (...args: unknown[]) => Promise<unknown>;
    gp_list_new: (...args: unknown[]) => Promise<number>;
    gp_list_unref: (...args: unknown[]) => Promise<number>;
    gp_list_count: (...args: unknown[]) => Promise<number>;
    gp_list_get_name: (...args: unknown[]) => Promise<number>;
    gp_list_get_value: (...args: unknown[]) => Promise<number>;
    gp_camera_autodetect: (...args: unknown[]) => Promise<number>;
    gp_camera_new: (...args: unknown[]) => Promise<number>;
    gp_camera_set_abilities: (...args: unknown[]) => Promise<number>;
    gp_camera_set_port_info: (...args: unknown[]) => Promise<number>;
    gp_camera_init: (...args: unknown[]) => Promise<number>;
    gp_camera_get_summary: (...args: unknown[]) => Promise<number>;
    gp_camera_trigger_capture: (...args: unknown[]) => Promise<number>;
    gp_camera_capture_preview: (...args: unknown[]) => Promise<number>;
    gp_camera_wait_for_event: (...args: unknown[]) => Promise<number>;
    gp_camera_file_get: (...args: unknown[]) => Promise<number>;
    gp_camera_file_delete: (...args: unknown[]) => Promise<number>;
    gp_camera_get_config: (...args: unknown[]) => Promise<number>;
    gp_camera_set_config: (...args: unknown[]) => Promise<number>;
    gp_camera_exit: (...args: unknown[]) => Promise<number>;
    gp_camera_unref: (...args: unknown[]) => Promise<number>;
    gp_widget_count_children: (...args: unknown[]) => Promise<number>;
    gp_widget_get_child: (...args: unknown[]) => Promise<number>;
    gp_widget_get_child_by_name: (...args: unknown[]) => Promise<number>;
    gp_widget_get_child_by_label: (...args: unknown[]) => Promise<number>;
    gp_widget_get_name: (...args: unknown[]) => Promise<number>;
    gp_widget_get_label: (...args: unknown[]) => Promise<number>;
    gp_widget_get_readonly: (...args: unknown[]) => Promise<number>;
    gp_widget_get_type: (...args: unknown[]) => Promise<number>;
    gp_widget_get_range: (...args: unknown[]) => Promise<number>;
    gp_widget_count_choices: (...args: unknown[]) => Promise<number>;
    gp_widget_get_choice: (...args: unknown[]) => Promise<number>;
    gp_widget_get_value_string: (...args: unknown[]) => Promise<number>;
    gp_widget_get_value_float: (...args: unknown[]) => Promise<number>;
    gp_widget_set_value: (...args: unknown[]) => Promise<number>;
    gp_widget_unref: (...args: unknown[]) => Promise<number>;
    gp_file_new: (...args: unknown[]) => Promise<number>;
    gp_file_new_from_fd: (...args: unknown[]) => Promise<number>;
    gp_file_get_data_and_size: (...args: unknown[]) => Promise<number>;
    gp_file_get_mime_type: (...args: unknown[]) => Promise<number>;
    gp_file_free: (...args: unknown[]) => Promise<number>;
    open: (...args: unknown[]) => Promise<unknown>;
    fchmod: (...args: unknown[]) => Promise<unknown>;
};

declare enum WidgetType {
    Window = 0,
    Section = 1,
    Text = 2,
    Range = 3,
    Toggle = 4,
    Radio = 5,
    Menu = 6,
    Button = 7,
    Date = 8
}
interface CameraInfo {
    name: string;
    port: string;
}
interface CameraFilePath {
    name: string;
    folder: string;
}
declare enum CameraEventType {
    Unknown = 0,
    Timeout = 1,
    FileAdded = 2,
    FolderAdded = 3,
    CaptureComplete = 4,
    FileChanged = 5
}
interface CameraEventUnknown {
    type: CameraEventType.Unknown;
}
interface CameraEventTimeout {
    type: CameraEventType.Timeout;
}
interface CameraEventFileAdded {
    type: CameraEventType.FileAdded;
    path: CameraFilePath;
}
interface CameraEventFolderAdded {
    type: CameraEventType.FolderAdded;
    path: CameraFilePath;
}
interface CameraEventCaptureComplete {
    type: CameraEventType.CaptureComplete;
}
interface CameraEventFileChanged {
    type: CameraEventType.FileChanged;
    path: CameraFilePath;
}
type CameraEvent = CameraEventUnknown | CameraEventTimeout | CameraEventFileAdded | CameraEventFolderAdded | CameraEventCaptureComplete | CameraEventFileChanged;
interface CameraModule {
    listAsync(): Promise<CameraInfo[]>;
    openAsync(camera: CameraInfo): Promise<void>;
    closeAsync(cameraInfo: CameraInfo): Promise<boolean>;
    summaryAsync(cameraInfo: CameraInfo): Promise<string>;
    triggerCaptureAsync(cameraInfo: CameraInfo): Promise<void>;
    triggerCapturePreviewAsync(cameraInfo: CameraInfo): Promise<{
        data: Uint8Array;
        size: number;
        mimeType: string;
    }>;
    getConfigAsync(cameraInfo: CameraInfo, options?: {
        /**
         * Supply a function to filter which config items will be returned. Return true to include the item, false to exclude it.
         */
        filter?: (name: string, type: WidgetType) => boolean;
        /**
         * Set to true to only include config which which are not read only
         */
        ignoreReadOnly?: boolean;
    }): Promise<{
        [key: string]: string | number | boolean;
    }>;
    getConfigWidgetsAsync(cameraInfo: CameraInfo, options?: {
        /**
         * Supply a function to filter which config items will be returned. Return true to include the item, false to exclude it.
         */
        filter?: (name: string, type: WidgetType) => boolean;
        /**
         * Set to true to only include config which which are not read only
         */
        ignoreReadOnly?: boolean;
    }): Promise<{
        [key: string]: ConfigWidget;
    }>;
    setConfigAsync(cameraInfo: CameraInfo, newConfig: {
        [key: string]: string | number | boolean;
    }, options?: {
        ignoreErrors?: boolean;
    }): Promise<void>;
    waitForEventAsync(cameraInfo: CameraInfo, timeoutMilliseconds: number): Promise<CameraEvent>;
    getFileAsync(cameraInfo: CameraInfo, cameraFilePath: CameraFilePath, targetFilePath: string): Promise<void>;
}
interface TextConfigWidget {
    type: WidgetType.Text;
    label: string;
    value: string;
}
interface RangeConfigWidget {
    type: WidgetType.Range;
    label: string;
    value: number;
    min: number;
    max: number;
    increment: number;
}
interface ToggleConfigWidget {
    type: WidgetType.Toggle;
    label: string;
    value: boolean;
}
interface ChoiceConfigWidget {
    type: WidgetType.Radio | WidgetType.Menu;
    label: string;
    value: string;
    choices: string[];
}
type ConfigWidget = TextConfigWidget | RangeConfigWidget | ToggleConfigWidget | ChoiceConfigWidget;

/**
 * Do the actual loading of the library
 */
declare const loadInternal: () => Promise<CameraModule & {
    ffi: ReturnType<typeof getFfi>;
}>;
/**
 * Load the library and return the interface and methods
 */
declare const load: () => Promise<CameraModule & {
    ffi: ReturnType<typeof getFfi>;
}>;

export { type CameraEvent, type CameraEventCaptureComplete, type CameraEventFileAdded, type CameraEventFileChanged, type CameraEventFolderAdded, type CameraEventTimeout, CameraEventType, type CameraEventUnknown, type CameraFilePath, type CameraInfo, type CameraModule, type ChoiceConfigWidget, type ConfigWidget, type RangeConfigWidget, type TextConfigWidget, type ToggleConfigWidget, WidgetType, load, loadInternal };
