import { Directive, DefineComponent, ExtractPropTypes, AllowedComponentProps, ComponentCustomProps, VNodeProps, Ref, EmitsOptions, ObjectEmitsOptions, Component, GlobalComponents, VNodeChild, GlobalDirectives, Slot, defineComponent } from '@vue/runtime-core';

declare function checkDirective<
  T,
  D extends
    | Directive<T, unknown>
    | 'show'
    | 'text'
    | 'html'
    | 'once'
    | 'pre'
    | 'cloak'
    | 'memo',
  A extends string | undefined,
  E extends GetExp$2<T, D>,
  M extends GetModifiers$2<D>
>(dir: D, tag: T, arg: A, exp: E, modifiers: Partial<Record<M, boolean>>): E

type GetExp$2<T, D> = D extends 'show'
  ? boolean | undefined
  : D extends 'text' | 'html'
  ? T extends keyof JSX.IntrinsicElements
    ? string | undefined
    : T extends JSX.IntrinsicAttributes[keyof JSX.IntrinsicAttributes]
    ? string | undefined
    : never
  : D extends 'once' | 'pre' | 'cloak'
  ? undefined
  : D extends 'memo'
  ? any[]
  : D extends Directive<unknown, infer E>
  ? E
  : undefined

type GetModifiers$2<D> = D extends Directive<unknown, unknown> ? never : never

/* eslint-disable @typescript-eslint/prefer-function-type */
type TupleToUnion<T> = T extends Readonly<[infer F, ...infer R]>
  ? F | TupleToUnion<R>
  : T extends Readonly<Array<infer R>>
  ? R
  : never

type UnwrapArray<T> = T extends Array<infer I> ? I : T extends ReadonlyArray<infer I> ? I : T;

type UnionToIntersection<U> =
  (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;

type OnlyEventNames<K extends string | number | symbol> = K extends `on${Capitalize<string>}` ? K : never

// prettier-ignore
type EventName<T extends string> = `on${Capitalize<T>}`

// prettier-ignore
type RemoveOnPrefix<T extends string> = T extends `on${infer K}` ? Uncapitalize<K> : T

type Overloads<T> =
  T extends {
    (...args: infer A1): infer R1;
    (...args: infer A2): infer R2;
    (...args: infer A3): infer R3;
    (...args: infer A4): infer R4;
    (...args: infer A5): infer R5;
    (...args: infer A6): infer R6;
  } ? [
    (...args: A1) => R1,
    (...args: A2) => R2,
    (...args: A3) => R3,
    (...args: A4) => R4,
    (...args: A5) => R5,
    (...args: A6) => R6
  ] : T extends {
    (...args: infer A1): infer R1;
    (...args: infer A2): infer R2;
    (...args: infer A3): infer R3;
    (...args: infer A4): infer R4;
    (...args: infer A5): infer R5;
  } ? [
    (...args: A1) => R1,
    (...args: A2) => R2,
    (...args: A3) => R3,
    (...args: A4) => R4,
    (...args: A5) => R5
  ] : T extends {
    (...args: infer A1): infer R1;
    (...args: infer A2): infer R2;
    (...args: infer A3): infer R3;
    (...args: infer A4): infer R4
  } ? [
    (...args: A1) => R1,
    (...args: A2) => R2,
    (...args: A3) => R3,
    (...args: A4) => R4
  ] : T extends {
    (...args: infer A1): infer R1;
    (...args: infer A2): infer R2;
    (...args: infer A3): infer R3
  } ? [
    (...args: A1) => R1,
    (...args: A2) => R2,
    (...args: A3) => R3
  ] : T extends {
    (...args: infer A1): infer R1;
    (...args: infer A2): infer R2
  } ? [
    (...args: A1) => R1,
    (...args: A2) => R2
  ] : T extends {
    (...args: infer A1): infer R1
  } ? [
    (...args: A1) => R1
  ] : any


type KnownKeys<T> = {
  [K in keyof T as string extends K
  ? never
  : number extends K
  ? never
  : K]: T[K];
}

type FlatArray<Arr, Depth extends number> = {
  "done": Arr,
  "recur": Arr extends ReadonlyArray<infer InnerArr>
      ? FlatArray<InnerArr, [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20][Depth]>
      : Arr
}[Depth extends -1 ? "done" : "recur"];


declare function flat<T extends unknown[], D extends number = 1>(
  array: T,
  depth?: D
): Array<FlatArray<T, D>>

declare function union<T extends unknown[]>(...args: T): TupleToUnion<T>

type Get<T, K, F = never> = K extends keyof T ? T[K] : F

type ComponentLike<T> = new (...args: unknown[]) => { $props: T }

type PropsOf<T> = T extends ComponentLike<infer Props>
  ? Props
  : T extends (props: infer Props) => unknown
  ? Props
  : T extends DefineComponent<infer PropsOrPropOptions>
  ? ExtractPropTypes<PropsOrPropOptions>
  : T extends KnownKeys<keyof JSX.IntrinsicElements>
  ? JSX.IntrinsicElements[T]
  : AllowedComponentProps & ComponentCustomProps & VNodeProps

type AttrsOf<T> = T extends KnownKeys<keyof JSX.IntrinsicElements>
  ? JSX.IntrinsicElements[T]
  : {}

type MergeAttrs<P, A> = P & Omit<A, keyof KnownKeys<P>>

declare function propCompletionHelper<T>(
  propName: keyof PropsOf<T>,
  tagOrComponent: T,
): any

declare function checkModelDirective<
  T,
  A extends GetArg$1<T>,
  O extends {},
  E extends GetExp$1<T, A, O>,
  M extends GetModifiers$1<T>
>(
  tag: T,
  arg: A,
  exp: E,
  modifiers: Partial<Record<M, boolean>>,
  options?: O,
): E

type GetArg$1<T> = T extends 'input' | 'textarea' | 'select'
  ? undefined
  : T extends KnownKeys<keyof JSX.IntrinsicElements>
  ? never
  : keyof PropsOf<T>

type GetExp$1<T, A, O> = T extends 'textarea'
  ? string
  : T extends 'input'
  ? InputValueType<O> | undefined | null
  : T extends 'select'
  ? SelectValueType<O>
  : T extends KnownKeys<keyof JSX.IntrinsicElements>
  ? never
  : Get<PropsOf<T>, A>

type GetModifiers$1<T> = T extends 'input' | 'textarea' | 'select'
  ? 'lazy' | 'number' | 'trim'
  : never // acts as a catch-all

type InputValueType<O> = O extends { type: infer T }
  ? T extends 'checkbox'
    ? O extends { checkbox: infer C }
      ? C extends [infer Y, infer N]
        ? Y | N
        : TupleToUnion<C>
      : boolean
    : T extends 'radio'
    ? O extends { radio: infer R }
      ? TupleToUnion<R>
      : string
    : T extends 'date' | 'datetime' | 'datetime-local'
    ? string | Date
    : T extends 'number' | 'range'
    ? string | number
    : T extends 'button' | 'reset' | 'submit'
    ? never
    : string
  : string

type SelectValueType<O> = O extends { option: infer T }
  ? TupleToUnion<T>
  : string

declare function checkHTMLElementType<K extends string>(
  tag: K,
  instance: unknown,
): instance is K extends keyof HTMLElementTagNameMap
  ? HTMLElementTagNameMap[K]
  : K extends keyof SVGElementTagNameMap
  ? SVGElementTagNameMap[K]
  : EventTarget

declare function checkOnDirective<
  T,
  A extends GetArg<T>,
  E extends GetExp<T, A>,
  M extends GetModifiers<T, A>
>(tag: T, arg: A, exp: E, modifiers: Partial<Record<M, boolean>>): E

type MouseEventNames =
  | 'auxclick'
  | 'click'
  | 'contextmenu'
  | 'dbclick'
  | 'mousedown'
  | 'mouseenter'
  | 'mousemove'
  | 'mouseleave'
  | 'mouseout'
  | 'mouseover'
  | 'mouseup'
  | 'wheel'
type PointerEventNames =
  | 'pointerdown'
  | 'pointermove'
  | 'pointerup'
  | 'pointercancel'
  | 'pointerenter'
  | 'pointerleave'
  | 'pointerover'
  | 'pointerout'
type KeyboardEventNames = 'keydown' | 'keypress' | 'keyup'
type ModifiersForNativeEvent<EventName> =
  | 'once'
  | 'stop'
  | 'prevent'
  | 'capture'
  | 'self'
  | 'passive'
  | (EventName extends KeyboardEventNames
      ?
          | 'enter'
          | 'tab'
          | 'delete'
          | 'esc'
          | 'space'
          | 'left'
          | 'right'
          | 'up'
          | 'down'
          | 'ctrl'
          | 'alt'
          | 'shift'
          | 'meta'
          | 'exact'
      : never)
  | (EventName extends PointerEventNames
      ?
          | 'left'
          | 'right'
          | 'middle'
          | 'ctrl'
          | 'alt'
          | 'shift'
          | 'meta'
          | 'exact'
      : never)
  | (EventName extends MouseEventNames
      ?
          | 'left'
          | 'right'
          | 'middle'
          | 'ctrl'
          | 'alt'
          | 'shift'
          | 'meta'
          | 'exact'
      : never)

type GetArg<T> = RemoveOnPrefix<OnlyEventNames<keyof PropsOf<T>>>

type GetExp<T, A extends GetArg<T>> = Get<PropsOf<T>, EventName<A>>

type GetModifiers<T, A> = T extends keyof KnownKeys<JSX.IntrinsicElements>
  ? A extends GetArg<T>
    ? ModifiersForNativeEvent<A>
    : never
  : never

declare function checkInterpolation(
  value: string | boolean | number | null | undefined,
): string

/**
 * @deprecated - You should not be using interpolation to render objects.
 */
declare function checkInterpolation(value: object | symbol | unknown[]): string

type RefValue<T> = T extends (value: infer V) => unknown ? V : T

declare function checkRef<T>(
  ref: T | ((value: T) => unknown) | null,
  element: RefValue<T>,
): Ref<T>

type SlotsFrom<T> = T extends abstract new (...args: unknown[]) => { $slots: infer Slots } ? Slots : {}

declare function checkSlots<T>(tag: T, slots: Partial<SlotsFrom<T>>): any

type EmitsToProps<T extends EmitsOptions> = T extends string[] ? {
  [K in string & EventName<T[number]>]?: (...args: any[]) => any;
} : T extends ObjectEmitsOptions ? {
  [K in string & EventName<Capitalize<string & keyof T>>]?: K extends `on${infer C}` ? T[Uncapitalize<C>] extends null ? (...args: any[]) => any : (...args: T[Uncapitalize<C>] extends (...args: infer P) => any ? P : never) => any : never;
} : {};

/* eslint-disable @typescript-eslint/no-empty-interface */


declare global {
  namespace JSX {
    interface IntrinsicElements {}
    interface IntrinsicAttributes {}
  }
}

declare module '@vue/runtime-core' {
  export interface GlobalComponents extends Record<string, Component> {}
}

type ComponentFromProps<P> = new () => {
  $props: P
  $slots: { default(): VNodeChild }
}

declare function resolveComponent<T extends {}, A, B>(
  localRegisteredComponents: T,
  tagNameOrComponent: A,
  tagNameInPascalName?: B,
): A extends Component
  ? A
  : A extends keyof KnownKeys<T>
  ? T[A]
  : B extends keyof KnownKeys<T>
  ? T[B]
  : A extends keyof KnownKeys<JSX.IntrinsicElements>
  ? ComponentFromProps<JSX.IntrinsicElements[A]>
  : B extends keyof KnownKeys<JSX.IntrinsicElements>
  ? ComponentFromProps<JSX.IntrinsicElements[B]>
  : A extends keyof KnownKeys<GlobalComponents>
  ? GlobalComponents[A]
  : B extends keyof KnownKeys<GlobalComponents>
  ? GlobalComponents[B]
  : never

type TypeEmitsToOptions<
  T,
  TU = TupleToUnion<Overloads<T>>
> = UnionToIntersection<
  TU extends (eventName: infer P, ...rest: infer A) => infer R
    ? P extends string
      ? { [K in P]: (...args: A) => R }
      : {}
    : {}
>
type ToEmitOptions<T> = T extends (...args: any) => any
  ? TypeEmitsToOptions<T> & {}
  : T extends EmitsOptions
  ? T
  : {}

declare function defineSetupComponent<P, E, B>(
  props: P,
  emits: E,
  bindings: B,
  options: any,
): DefineComponent<
  {}, // PropsOrPropOptions
  B, // RawBindings
  {}, // D
  {}, // C = ComputedOptions
  {}, // M = MethodOptions
  {}, // Mixin
  {}, // Extends
  {}, // E = EmitsOptions
  string, // EE
  VNodeProps & AllowedComponentProps & ComponentCustomProps, // PP = PublicProps
  P & EmitsToProps<ToEmitOptions<E>>, // Props
  {} // Defaults
>

/* eslint-disable @typescript-eslint/no-empty-interface */


declare module '@vue/runtime-core' {
  interface GlobalDirectives {}
}

declare function resolveDirective<T extends {}, A, B>(
  localRegisteredDirectives: T,
  directiveName: A,
  directiveNameInCamelCase?: B,
): A extends keyof KnownKeys<T>
  ? T[A]
  : B extends keyof KnownKeys<T>
  ? T[B]
  : A extends keyof KnownKeys<GlobalDirectives>
  ? GlobalDirectives[A]
  : B extends keyof KnownKeys<GlobalDirectives>
  ? GlobalDirectives[B]
  : never

type ElementType<E> = E extends string
  ? E extends keyof KnownKeys<HTMLElementTagNameMap>
    ? HTMLElementTagNameMap[E]
    : E extends keyof KnownKeys<SVGElementTagNameMap>
    ? SVGElementTagNameMap[E]
    : never
  : E

declare function getElementType<T>(tagNameOrComponent: T): ElementType<T>

declare function renderList<R>(
  source: string,
  handler: (value: string, index: number) => R,
): R[]
declare function renderList<R>(
  source: number,
  handler: (value: number, index: number) => R,
): R[]
declare function renderList<R>(
  source: number,
  handler: (value: number, index: number) => R,
): R[]
declare function renderList<T, R>(
  source: T[],
  handler: (value: T, index: number) => R,
): R[]
declare function renderList<T extends Readonly<unknown[]>, R>(
  source: T,
  handler: (value: TupleToUnion<T>, index: number) => R,
): R[]
declare function renderList<T, R>(
  source: Iterable<T>,
  handler: (value: T, index: number) => R,
): R
declare function renderList<T extends object, R>(
  source: T,
  handler: <K extends keyof T>(value: T[K], key: K, index: number) => R,
): R[]

type Fallback<T, F> = T extends undefined ? F : T
type SlotProps<T extends Slot | undefined> = T extends (
  ...args: unknown[]
) => unknown
  ? Fallback<Parameters<T>[0], {}>
  : {}

// -- renderSlot --
declare function renderSlot<
  S extends Readonly<{
    [name: string]: Slot | undefined
  }>,
  K extends keyof S
>(source: S, name: K, props: SlotProps<S[K]>): any

type InternalSlots<T> = {
  [K in keyof T]: (props: T[K]) => VNodeChild
}

type KeysWithUndefinedValue<T> = {
  [P in keyof T]-?: Exclude<T[P], null | undefined> extends never ? never : P
}[keyof T]
type OmitUndefinedProperties<T> = Pick<T, KeysWithUndefinedValue<T>>
type NoNullable<T> = { [P in keyof T]-?: Exclude<T[P], null | undefined> }

type Slots<T> = InternalSlots<
  NoNullable<UnionToIntersection<OmitUndefinedProperties<UnwrapArray<T>>>>
>

/* eslint-disable @typescript-eslint/no-empty-interface */


type version = '3.x'

declare global {
  namespace VueDX {
    namespace internal {
      export { flat, union }
      export { resolveComponent, resolveDirective, getElementType }
      export { renderList, renderSlot, Slots }
      export { defineComponent, defineSetupComponent }
      export {
        checkInterpolation,
        checkRef,
        checkSlots,
        checkDirective,
        checkOnDirective,
        checkHTMLElementType,
        checkModelDirective,
      }
      export { propCompletionHelper }
      export { PropsOf, AttrsOf, MergeAttrs }
    }
  }
}

export { version };
