import {IApiCollection} from "./IApiCollection";
import {
    ApiConfig,
    ExtractIApi, HangerIndex, ObjectMapping,
    ResponseHandlerDefineFunction,
    TransformFunction
} from "./TypeDefine";
import {IApiHandler} from "./IApiHandler";
import {ApiHandlerAxios} from "./ApiHandlerAxios";
import {IApiParamsCollection} from "./IApiParamsCollection";
import {ApiHandlerFetch} from "./ApiHandlerFetch";
import {IApi} from "./IApi";
import {ApiHandler} from "./ApiHandler";

class ApiFactory {
    responseHandlerDefineFunction: ResponseHandlerDefineFunction;
    apiConfig: ApiConfig
    hanger: HangerIndex<any> | HangerIndex<any>[] | undefined

    constructor(responseHandlerDefineFunction: ResponseHandlerDefineFunction, apiConfig: ApiConfig, hanger?: HangerIndex<any> | HangerIndex<any>[]) {
        this.responseHandlerDefineFunction = responseHandlerDefineFunction;
        this.apiConfig = apiConfig;
        this.hanger = hanger;
    }


    processApiCollection<T extends IApiCollection>(apiCollection: T, basePath: string, hanger?: HangerIndex<any> | HangerIndex<any>[]): TransformFunction<T> {
        const apiHandlers: ObjectMapping<string, any> = {};
        for (const apiCollectionKey in apiCollection) {
            apiHandlers[apiCollectionKey] = this.factory(apiCollectionKey, apiCollection[apiCollectionKey], basePath, hanger);
        }
        return apiHandlers as TransformFunction<T>;
    }

    private factory<T extends IApiParamsCollection>(apiCollectionKey: string, api: IApi, basePath: string, hanger?: HangerIndex<any> | HangerIndex<any>[]): IApiHandler<T> {
        const newApi = {...api};
        if (typeof api.path === "undefined")
            api.path = apiCollectionKey;
        newApi.path = basePath + "/" + api.path;
        if (typeof api.hanger === 'undefined')
            newApi.hanger = [];
        else {
            if (!Array.isArray(api.hanger))
                newApi.hanger = [api.hanger]
        }
        if (hanger) {
            if (Array.isArray(hanger))
                (<HangerIndex<any>[]>newApi.hanger).push(...hanger)
            else (<HangerIndex<any>[]>newApi.hanger).push(hanger)
        }
        if (this.hanger) {
            if (Array.isArray(this.hanger))
                (<HangerIndex<any>[]>newApi.hanger).push(...this.hanger)
            else (<HangerIndex<any>[]>newApi.hanger).push(this.hanger)
        }
        switch (this.apiConfig.type) {
            case "fetch":
                return new ApiHandlerFetch(newApi, this.responseHandlerDefineFunction, this.apiConfig.config);
            case "axios":
                this.apiConfig.config.defaults.baseURL = "";
                return new ApiHandlerAxios(newApi, this.responseHandlerDefineFunction, this.apiConfig.config);
        }

    }
}

export {ApiFactory}