declare interface AsixMovmentData {
    /**
     * @case 0: Horizontal axis for left stick (negative left/positive right)
     * @case 1: Vertical axis for left stick (negative up/positive down)
     * @case 2: Horizontal axis for right stick (negative left/positive right)
     * @case 3: Vertical axis for right stick (negative up/positive down)
     */
    axis: number;
    axisMovementValue: number;
    directionOfMovement: DirectionOfMovement;
    gamepad: Gamepad;
    stickMoved: StickMoved;
    totalSticks: number;
}

export declare interface AxisMoveEvent extends CustomEvent {
    detail: AsixMovmentData;
}

declare interface ButtonPressData {
    button: GamepadButton;
    buttonName: string;
    gamepad: Gamepad;
    /**
     * @case 0: A
     * @case 1: B
     * @case 2: X
     * @case 3: Y
     * @case 4: LT
     * @case 5: RT
     * @case 6: LB
     * @case 7: RB
     * @case 8: SELECT
     * @case 9: START
     * @case 10: Left stick pressed button
     * @case 11: Right stick pressed button
     * @case 12: D-pad up
     * @case 13: D-pad down
     * @case 14: D-pad left
     * @case 15: D-pad right
     * @case 16: Vendor button 1
     * @case 17: Vendor button 2
     */
    index: number;
}

export declare interface ButtonPressEvent extends CustomEvent {
    detail: ButtonPressData;
}

declare type DirectionOfMovement = "top" | "bottom" | "left" | "right";

declare enum EventEnum {
    CONNECT_NATIVE = "gamepadconnected",
    CONNECT_ALIAS = "connect",
    DISCONNECT_NATIVE = "gamepaddisconnected",
    DISCONNECT_ALIAS = "disconnect",
    BUTTON_PRESS_ALIAS = "button_press",
    BUTTON_RELEASE_ALIAS = "button_release",
    AXIS_MOVEMENT_ALIAS = "axis_move"
}

declare type EventMap = {
    "gamepadconnected": [event: GamepadEvent];
    "connect": [event: GamepadEvent];
    "gamepaddisconnected": [event: GamepadEvent];
    "disconnect": [event: GamepadEvent];
    "button_press": [event: ButtonPressEvent];
    "button_release": [event: ButtonPressEvent];
    "axis_move": [event: AxisMoveEvent];
};

declare class Joypad {
    loopStarted: boolean;
    instances: Record<number | string, Gamepad>;
    buttonEvents: {
        joypad: (Record<string, JoypadItem> | null)[];
    };
    settings: JoypadSettings;
    remove(index: number): boolean;
    on<TEventName extends keyof EventMap & string>(event: TEventName, callback: (...eventArg: EventMap[TEventName]) => void): {
        unsubscribe: () => void;
    } | undefined;
    vibrate(gamepadInstance: Gamepad, options?: GamepadEffectParameters): Promise<GamepadHapticsResult> | undefined;
    set(settings: JoypadSettings): void;
    trigger(event: EventEnum, data: unknown): void;
}

declare const joypad: Joypad;
export default joypad;

declare type JoypadItem = {
    index?: number;
    gamepad?: Gamepad;
    pressed: boolean;
    hold: boolean;
    released: boolean;
    last_event?: EventEnum;
    button?: GamepadButton;
};

declare interface JoypadSettings {
    vibration?: {
        startDelay: number;
        duration: number;
        weakMagnitude: number;
        strongMagnitude: number;
    };
    axisMovementThreshold?: number;
    customButtonMapping?: Record<string, number>;
}

declare type StickMoved = "left_stick" | "right_stick";

export { }
