/*
 Городим огород, чтоб vue-property-decorator работал с абстрактными классами.
 Пока не работает в @Component({mixins: [X]}), только через extends Mixins(X);
 */

import Vue, { ComponentOptions } from 'vue';
import Component, { mixins } from 'vue-class-component';
import { VueClass } from 'vue-class-component/lib/declarations';

// eslint-disable-next-line @typescript-eslint/ban-types
export type VueAbstractClass<V extends Vue> = Function & {
  prototype: V;
};

export type VC<V extends Vue> = VueAbstractClass<V> | VueClass<V>;

declare function MixinD<V extends Vue>(
  options: ComponentOptions<V> & ThisType<V>
): <MC extends VC<V>>(target: MC) => MC & V;
declare function MixinD<MC extends VC<V>, V extends Vue>(target: MC): MC & V;

export const Mixin = Component as typeof MixinD;

declare function MixinsDeclaration<A extends Vue>(CtorA: VC<A>): VueClass<A>;
declare function MixinsDeclaration<A extends Vue, B extends Vue>(
  CtorA: VC<A>,
  CtorB: VC<B>
): VueClass<A & B>;
declare function MixinsDeclaration<A extends Vue, B extends Vue, C extends Vue>(
  CtorA: VC<A>,
  CtorB: VC<B>,
  CtorC: VC<C>
): VueClass<A & B & C>;
declare function MixinsDeclaration<
  A extends Vue,
  B extends Vue,
  C extends Vue,
  D extends Vue
>(
  CtorA: VC<A>,
  CtorB: VC<B>,
  CtorC: VC<C>,
  CtorD: VC<D>
): VueClass<A & B & C & D>;
declare function MixinsDeclaration<
  A extends Vue,
  B extends Vue,
  C extends Vue,
  D extends Vue,
  E extends Vue
>(
  CtorA: VC<A>,
  CtorB: VC<B>,
  CtorC: VC<C>,
  CtorD: VC<D>,
  CtorE: VC<E>
): VueClass<A & B & C & D & E>;
declare function MixinsDeclaration<T extends Vue>(
  ...Ctors: VC<Vue>[]
): VueClass<T>;

export const Mixins = mixins as typeof MixinsDeclaration;
