import "reflect-metadata";
import * as Redux from "redux";
import { Constructable } from "../../types/constructable";
import { METADATA_KEY } from "../../constants/metadata.keys";
import { ERRORS_MSGS } from "../../constants/error-msgs";
import { BaseProvider } from "../provider/provider";
import { ActionHandlerType } from "../action/action";

export interface ReduxProviderModuleOptions {
	providers?: Constructable<BaseProvider>[];
	middlewares?: Redux.Middleware[];
	actions: {
		[actionHandler: string]: Constructable<ActionHandlerType>;
	};
	rootReducer: Redux.Reducer<any, Redux.AnyAction>;
	initialState?: any;
}
export abstract class AbstractReduxModule {}
export function ReduxModule<T extends AbstractReduxModule>(options: ReduxProviderModuleOptions) {
	return (moduleTarget: Constructable<T>): void => {
		if (Reflect.hasOwnMetadata(METADATA_KEY.REDUX_PROVIDER_MODULE_PARAM_TYPES, moduleTarget)) {
			throw new Error(ERRORS_MSGS.DUPLICATED_REDUX_MODULE_DECORATOR);
		}
		const types = Reflect.getMetadata(METADATA_KEY.DESIGN_PARAM_TYPES, moduleTarget) || [];
		Reflect.defineMetadata(METADATA_KEY.REDUX_PROVIDER_MODULE_PARAM_TYPES, types, moduleTarget);
		Reflect.defineMetadata(METADATA_KEY.REDUX_PROVIDER_MODULE_OPTIONS, options, moduleTarget);
	};
}
