import { AbstractInterface } from '@midscene/core/device';
import type { ActionParam } from '@midscene/core';
import type { ActionReturn } from '@midscene/core';
import { Agent } from '@midscene/core/agent';
import { AgentOpt } from '@midscene/core/agent';
import { BaseMCPServer } from '@midscene/shared/mcp';
import { BaseMidsceneTools } from '@midscene/shared/mcp';
import { DeviceAction } from '@midscene/core';
import type { ElementInfo } from '@midscene/shared/extractor';
import { InterfaceType } from '@midscene/core';
import { IOSDeviceInputOpt } from '@midscene/core/device';
import { IOSDeviceOpt } from '@midscene/core/device';
import { LaunchMCPServerOptions } from '@midscene/shared/mcp';
import { LaunchMCPServerResult } from '@midscene/shared/mcp';
import { Point } from '@midscene/core';
import { Size } from '@midscene/core';
import { Tool } from '@midscene/shared/mcp';
import { ToolDefinition } from '@midscene/shared/mcp';
import { z } from '@midscene/core';

declare type ActionArgs<T extends DeviceAction> = [ActionParam<T>] extends [undefined] ? [] : [ActionParam<T>];

declare type DeviceActionIOSAppSwitcher = DeviceAction<undefined, void>;

declare type DeviceActionIOSHomeButton = DeviceAction<undefined, void>;

declare type DeviceActionLaunch = DeviceAction<LaunchParam, void>;

declare type DeviceActionRunWdaRequest = DeviceAction<RunWdaRequestParam, RunWdaRequestReturn>;

declare class IOSAgent extends Agent<IOSDevice> {
    /**
     * Launch an iOS app or URL
     * Type-safe wrapper around the Launch action from actionSpace
     */
    launch: WrappedAction<DeviceActionLaunch>;
    /**
     * Execute WebDriverAgent API request directly
     * Type-safe wrapper around the RunWdaRequest action from actionSpace
     */
    runWdaRequest: WrappedAction<DeviceActionRunWdaRequest>;
    /**
     * Trigger the system home operation on iOS devices
     */
    home: WrappedAction<DeviceActionIOSHomeButton>;
    /**
     * Trigger the system app switcher operation on iOS devices
     */
    appSwitcher: WrappedAction<DeviceActionIOSAppSwitcher>;
    /**
     * User-provided app name to bundle ID mapping
     */
    private appNameMapping;
    constructor(device: IOSDevice, opts?: IOSAgentOpt);
    private createActionWrapper;
}

declare type IOSAgentOpt = AgentOpt & {
    /**
     * Custom mapping of app names to bundle IDs
     * User-provided mappings will take precedence over default mappings
     */
    appNameMapping?: Record<string, string>;
};

declare class IOSDevice implements AbstractInterface {
    private deviceId;
    private devicePixelRatio;
    private devicePixelRatioInitialized;
    private destroyed;
    private description;
    private customActions?;
    private wdaBackend;
    private wdaManager;
    /** URL of WDA's native MJPEG server for real-time streaming */
    mjpegStreamUrl: string;
    private appNameMapping;
    interfaceType: InterfaceType;
    uri: string | undefined;
    options?: IOSDeviceOpt;
    actionSpace(): DeviceAction<any>[];
    constructor(options?: IOSDeviceOpt);
    describe(): string;
    getConnectedDeviceInfo(): Promise<{
        udid: string;
        name: string;
        model: string;
    } | null>;
    connect(): Promise<void>;
    /**
     * Set the app name to bundle ID mapping
     */
    setAppNameMapping(mapping: Record<string, string>): void;
    /**
     * Resolve app name to bundle ID using the mapping.
     * Comparison is case-insensitive and ignores spaces, dashes, and underscores.
     * Keys in appNameMapping are pre-normalized, so we only need to normalize the input.
     *
     * @param appName The app name to resolve.
     */
    private resolveBundleId;
    launch(uri: string): Promise<IOSDevice>;
    getElementsInfo(): Promise<ElementInfo[]>;
    getElementsNodeTree(): Promise<any>;
    private initializeDevicePixelRatio;
    getScreenSize(): Promise<{
        width: number;
        height: number;
        scale: number;
    }>;
    size(): Promise<Size>;
    screenshotBase64(): Promise<string>;
    clearInput(element?: ElementInfo): Promise<void>;
    url(): Promise<string>;
    tap(x: number, y: number): Promise<void>;
    mouseClick(x: number, y: number): Promise<void>;
    doubleTap(x: number, y: number): Promise<void>;
    tripleTap(x: number, y: number): Promise<void>;
    longPress(x: number, y: number, duration?: number): Promise<void>;
    swipe(fromX: number, fromY: number, toX: number, toY: number, duration?: number): Promise<void>;
    typeText(text: string, options?: IOSDeviceInputOpt): Promise<void>;
    pressKey(key: string): Promise<void>;
    scrollUp(distance?: number, startPoint?: Point): Promise<void>;
    scrollDown(distance?: number, startPoint?: Point): Promise<void>;
    scrollLeft(distance?: number, startPoint?: Point): Promise<void>;
    scrollRight(distance?: number, startPoint?: Point): Promise<void>;
    scrollUntilTop(startPoint?: Point): Promise<void>;
    scrollUntilBottom(startPoint?: Point): Promise<void>;
    private compareScreenshots;
    private scrollUntilBoundary;
    scrollUntilLeft(startPoint?: Point): Promise<void>;
    scrollUntilRight(startPoint?: Point): Promise<void>;
    home(): Promise<void>;
    appSwitcher(): Promise<void>;
    hideKeyboard(keyNames?: string[]): Promise<boolean>;
    /**
     * Open a URL using WebDriverAgent
     * @param url The URL to open (supports http://, https://, and custom schemes)
     * @param options Configuration options for URL opening
     */
    openUrl(url: string, options?: {
        useSafariAsBackup?: boolean;
        waitTime?: number;
    }): Promise<void>;
    /**
     * Open a URL via Safari (backup method for real devices)
     * @param url The URL to open
     */
    openUrlViaSafari(url: string): Promise<void>;
    /**
     * Execute a WebDriverAgent API request directly
     * This is the iOS equivalent of Android's runAdbShell
     * @param method HTTP method (GET, POST, DELETE, PUT)
     * @param endpoint WebDriver API endpoint
     * @param data Optional request body data
     * @returns Response from the WebDriver API
     */
    runWdaRequest<TResult = any>(method: WDAHttpMethod, endpoint: string, data?: any): Promise<TResult>;
    destroy(): Promise<void>;
}

/**
 * iOS MCP Server
 * Provides MCP tools for iOS automation through WebDriverAgent
 */
export declare class IOSMCPServer extends BaseMCPServer {
    constructor(toolsManager?: IOSMidsceneTools);
    protected createToolsManager(): IOSMidsceneTools;
}

/**
 * iOS-specific tools manager
 * Extends BaseMidsceneTools to provide iOS WebDriverAgent connection tools
 */
declare class IOSMidsceneTools extends BaseMidsceneTools<IOSAgent> {
    protected createTemporaryDevice(): IOSDevice;
    protected ensureAgent(): Promise<IOSAgent>;
    /**
     * Provide iOS-specific platform tools
     */
    protected preparePlatformTools(): ToolDefinition[];
}

declare type LaunchParam = z.infer<typeof launchParamSchema>;

declare const launchParamSchema: z.ZodString;

/**
 * Create MCP kit for a specific iOS Agent
 */
export declare function mcpKitForAgent(agent: Agent | IOSAgent): Promise<{
    description: string;
    tools: Tool[];
}>;

/**
 * Create an MCP server launcher for a specific iOS Agent
 */
export declare function mcpServerForAgent(agent: Agent | IOSAgent): {
    launch(options?: {
        verbose?: boolean;
    }): Promise<LaunchMCPServerResult>;
    launchHttp(options: LaunchMCPServerOptions): Promise<LaunchMCPServerResult>;
};

declare type RunWdaRequestParam = z.infer<typeof runWdaRequestParamSchema>;

declare const runWdaRequestParamSchema: z.ZodObject<{
    method: z.ZodEnum<["GET", "POST", "DELETE", "PUT"]>;
    endpoint: z.ZodString;
    data: z.ZodOptional<z.ZodObject<{}, "passthrough", z.ZodTypeAny, z.objectOutputType<{}, z.ZodTypeAny, "passthrough">, z.objectInputType<{}, z.ZodTypeAny, "passthrough">>>;
}, "strip", z.ZodTypeAny, {
    method: "POST" | "GET" | "DELETE" | "PUT";
    endpoint: string;
    data?: z.objectOutputType<{}, z.ZodTypeAny, "passthrough"> | undefined;
}, {
    method: "POST" | "GET" | "DELETE" | "PUT";
    endpoint: string;
    data?: z.objectInputType<{}, z.ZodTypeAny, "passthrough"> | undefined;
}>;

declare type RunWdaRequestReturn = Awaited<ReturnType<IOSDevice['runWdaRequest']>>;

/**
 * HTTP methods supported by WebDriverAgent API
 */
declare const WDA_HTTP_METHODS: readonly ["GET", "POST", "DELETE", "PUT"];

declare type WDAHttpMethod = (typeof WDA_HTTP_METHODS)[number];

/**
 * Helper type to convert DeviceAction to wrapped method signature
 */
declare type WrappedAction<T extends DeviceAction> = (...args: ActionArgs<T>) => Promise<ActionReturn<T>>;

export { }
