import { ActionContext, CommitOptions, DispatchOptions, GetterTree, MutationTree, Store as VuexStore } from "vuex";

type AugmentedActionContext<S, G extends GetterTree<S, S>, M extends MutationTree<S>, A extends ActionsType> = Omit<ActionContext<S, S>, "commit" | "dispatch" | "getters"> & {
	commit<K extends keyof M>(key: K, payload: Parameters<M[K]>[1]): ReturnType<M[K]>,
	dispatch<K extends keyof A, P extends Parameters<A[K]>[0]>(
		key: K,
		payload: P,
		options?: DispatchOptions
	): ReturnType<A[K]>,
	getters: { [K in keyof G]: ReturnType<G[K]> }
};

type ActionsType = {
	[key: string]: (payload?: any) => any
};

export type Actions<S, G extends GetterTree<S, S>, M extends MutationTree<S>, A extends ActionsType> = {
	[K in keyof A]: (context: AugmentedActionContext<S, G, M, A>, payload: Parameters<A[K]>[0]) => ReturnType<A[K]>
}

export type GenericStore<S, G extends GetterTree<S, S>, M extends MutationTree<S>, A extends ActionsType> = Omit<VuexStore<S>, "commit" | "getters" | "dispatch"> & {
	commit<K extends keyof M, P extends Parameters<M[K]>[1]>(
		key: K,
		payload: P,
		options?: CommitOptions
	): ReturnType<M[K]>,
	getters: { [K in keyof G]: ReturnType<G[K]> },
	dispatch<K extends keyof A, P extends Parameters<A[K]>[0]>(
		key: K,
		payload: P,
		options?: DispatchOptions
	): ReturnType<A[K]>
};
