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 { AgentBehaviorInitArgs } from '@midscene/shared/agent-tools/agent-behavior-init-args';
import { AgentOpt } from '@midscene/core/agent';
import { BaseMidsceneTools } from '@midscene/shared/agent-tools/base-tools';
import { DeviceAction } from '@midscene/core';
import type { ElementInfo } from '@midscene/shared/extractor';
import { HarmonyDeviceInputOpt as HarmonyDeviceInputOpt_2 } from '@midscene/core/device';
import { HarmonyDeviceOpt as HarmonyDeviceOpt_2 } from '@midscene/core/device';
import { InitArgSpec } from '@midscene/shared/agent-tools/base-tools';
import { InterfaceType } from '@midscene/core';
import { MobileInputPrimitives } from '@midscene/core/device';
import { overrideAIConfig } from '@midscene/shared/env';
import { PlaygroundPlatformDescriptor } from '@midscene/playground';
import { Point } from '@midscene/core';
import { Size } from '@midscene/core';
import type { ToolDefinition } from '@midscene/shared/agent-tools/types';

declare type ActionArgs<T extends DeviceAction> = [ActionParam<T>] extends [undefined] ? [] : [ActionParam<T>];

export declare function agentFromHdcDevice(deviceId?: string, opts?: HarmonyAgentOpt & HarmonyDeviceOpt): Promise<HarmonyAgent>;

declare type DeviceActionHarmonyBackButton = DeviceAction<undefined, void>;

declare type DeviceActionHarmonyHomeButton = DeviceAction<undefined, void>;

declare type DeviceActionHarmonyRecentAppsButton = DeviceAction<undefined, void>;

export declare function getConnectedDevices(hdcPath?: string, options?: HarmonyDeviceDiscoveryOptions): Promise<HarmonyDeviceInfo[]>;

export declare class HarmonyAgent extends Agent<HarmonyDevice> {
    back: WrappedAction<DeviceActionHarmonyBackButton>;
    home: WrappedAction<DeviceActionHarmonyHomeButton>;
    recentApps: WrappedAction<DeviceActionHarmonyRecentAppsButton>;
    constructor(device: HarmonyDevice, opts?: HarmonyAgentOpt);
    launch(uri: string): Promise<void>;
    terminate(uri: string): Promise<void>;
    runHdcShell(command: string): Promise<string>;
    private createActionWrapper;
}

export declare type HarmonyAgentOpt = AgentOpt & {
    /**
     * Custom mapping of app names to bundle names or explicit bundle/ability
     * targets. Bundle-only targets use bundle metadata to resolve their declared
     * launch ability. User-provided mappings take precedence over defaults.
     */
    appNameMapping?: Record<string, string>;
};

export declare class HarmonyDevice implements AbstractInterface {
    private deviceId;
    private hdc;
    private connecting;
    private destroyed;
    private descriptionText;
    private customActions?;
    private cachedScreenSize;
    private appNameMapping;
    private lastTapPosition;
    interfaceType: InterfaceType;
    uri: string | undefined;
    options?: HarmonyDeviceOpt;
    readonly inputPrimitives: MobileInputPrimitives;
    actionSpace(): DeviceAction<any>[];
    private performActionScroll;
    constructor(deviceId: string, options?: HarmonyDeviceOpt);
    describe(): string;
    connect(): Promise<HdcClient>;
    getHdc(): Promise<HdcClient>;
    /**
     * Set app-name aliases used by launch and terminate.
     * Keys are normalized here so callers do not need to know the internal
     * comparison format.
     */
    setAppNameMapping(mapping: Record<string, string>): void;
    private resolveMappedAppTarget;
    private resolveBundleNameForTerminate;
    launch(uri: string): Promise<HarmonyDevice>;
    /**
     * Terminate (force-stop) a HarmonyOS app by bundle name.
     * Supports app name resolution via setAppNameMapping.
     * If uri contains "/" (e.g. com.example.app/MainAbility), only the bundle part is used.
     */
    terminate(uri: string): Promise<void>;
    getScreenSize(): Promise<{
        width: number;
        height: number;
    }>;
    size(): Promise<Size>;
    private remoteScreenshotPath;
    private localScreenshotPath;
    screenshotBase64(): Promise<string>;
    private tapPoint;
    private doubleTapPoint;
    private longPressPoint;
    private typeText;
    clearInput(element?: ElementInfo): Promise<void>;
    private pressKey;
    scroll(deltaX: number, deltaY: number, speed?: number): Promise<void>;
    private scrollInDirection;
    scrollDown(distance?: number, startPoint?: Point): Promise<void>;
    scrollUp(distance?: number, startPoint?: Point): Promise<void>;
    scrollLeft(distance?: number, startPoint?: Point): Promise<void>;
    scrollRight(distance?: number, startPoint?: Point): Promise<void>;
    private scrollUntilEdge;
    scrollUntilTop(startPoint?: Point): Promise<void>;
    scrollUntilBottom(startPoint?: Point): Promise<void>;
    scrollUntilLeft(startPoint?: Point): Promise<void>;
    scrollUntilRight(startPoint?: Point): Promise<void>;
    back(): Promise<void>;
    home(): Promise<void>;
    recentApps(): Promise<void>;
    hideKeyboard(options?: HarmonyDeviceInputOpt): Promise<void>;
    /**
     * Get the current device-local time as a formatted string.
     * This avoids formatting a device timestamp in the host machine's timezone.
     */
    getDeviceLocalTimeString(format?: string): Promise<string>;
    destroy(): Promise<void>;
}

declare interface HarmonyDeviceDiscoveryOptions {
    timeout?: number;
}

declare interface HarmonyDeviceInfo {
    deviceId: string;
}

declare type HarmonyDeviceInputOpt = HarmonyDeviceInputOpt_2 & {
    keyboardDismissStrategy?: KeyboardDismissStrategy;
};

declare type HarmonyDeviceOpt = HarmonyDeviceOpt_2 & HarmonyDeviceInputOpt;

declare type HarmonyInitArgs = AgentBehaviorInitArgs & {
    deviceId?: string;
};

export declare class HarmonyMidsceneTools extends BaseMidsceneTools<HarmonyAgent, HarmonyInitArgs> {
    private lastInitArgsSignature?;
    protected getCliReportSessionName(): string;
    protected readonly initArgSpec: InitArgSpec<HarmonyInitArgs>;
    protected createTemporaryDevice(): HarmonyDevice;
    protected ensureAgent(initArgs?: HarmonyInitArgs): Promise<HarmonyAgent>;
    protected preparePlatformTools(): ToolDefinition[];
}

declare interface HarmonyPlatformOptions {
    deferConnection?: boolean;
    deviceId?: string;
    staticDir?: string;
    getAgentOptions?: () => HarmonyAgentOpt;
}

export declare const harmonyPlaygroundPlatform: PlaygroundPlatformDescriptor<HarmonyPlatformOptions | undefined>;

declare class HdcClient {
    private hdcPath;
    private deviceId;
    private timeout;
    private execMutex;
    private launchAbilityCache;
    constructor(options: HdcOptions);
    private buildArgs;
    exec(...args: string[]): Promise<string>;
    shell(command: string): Promise<string>;
    private assertUiInputSucceeded;
    private runUiInput;
    private buildPointerMovementArgs;
    fileSend(localPath: string, remotePath: string): Promise<void>;
    fileRecv(remotePath: string, localPath: string): Promise<void>;
    screenshot(remotePath: string): Promise<string>;
    click(x: number, y: number): Promise<void>;
    doubleClick(x: number, y: number): Promise<void>;
    longClick(x: number, y: number): Promise<void>;
    swipe(fromX: number, fromY: number, toX: number, toY: number, speed?: number): Promise<void>;
    fling(fromX: number, fromY: number, toX: number, toY: number, speed?: number): Promise<void>;
    drag(fromX: number, fromY: number, toX: number, toY: number, speed?: number): Promise<void>;
    inputText(x: number, y: number, text: string): Promise<void>;
    keyEvent(...keys: string[]): Promise<void>;
    /** Select all text in the focused field with Ctrl+A, then delete it. */
    clearTextField(): Promise<void>;
    startAbility(bundleName: string, abilityName: string, moduleName?: string): Promise<void>;
    private queryLaunchAbility;
    /**
     * Launch an app by bundle name using its system-declared entry ability.
     * Successful resolutions are cached for this HDC connection. If a cached
     * target becomes stale, it is queried again and retried only when it changed.
     */
    launchBundle(bundleName: string): Promise<void>;
    forceStop(bundleName: string): Promise<void>;
    getScreenInfo(): Promise<{
        width: number;
        height: number;
    }>;
    listTargets(): Promise<string[]>;
}

declare interface HdcOptions {
    hdcPath?: string;
    deviceId?: string;
    timeout?: number;
}

declare type KeyboardDismissStrategy = 'esc-first' | 'back-first';

export { overrideAIConfig }

declare type WrappedAction<T extends DeviceAction> = (...args: ActionArgs<T>) => Promise<ActionReturn<T>>;

export { }
