/*!
 * Built by ShiftSoftware
 * Copyright (c)
 */
import { smartInvokable } from "../blazor-ref/index";
import { fetchFrom } from "../../global/lib/fetch-from";
export const setPartLookupData = async (context, newData, { beforeAssignment } = {}) => {
    // @ts-ignore
    const loadingKey = (context === null || context === void 0 ? void 0 : context.localLoadingName) ? context === null || context === void 0 ? void 0 : context.localLoadingName : 'isLoading';
    if (newData === null || newData === undefined)
        newData = (context === null || context === void 0 ? void 0 : context.searchString) || '';
    // clears network timeoutRef which serves as await for animation
    clearTimeout(context.networkTimeoutRef);
    // handles request spam by canceling the previous ones
    if (context.abortController)
        context.abortController.abort();
    context.abortController = new AbortController();
    // syncing the internal timeout ref with external network ref
    let scopedTimeoutRef;
    const isSearchRequest = typeof newData === 'string';
    const searchString = typeof newData === 'string' ? newData : newData === null || newData === void 0 ? void 0 : newData.partNumber;
    try {
        if (!searchString || searchString.trim().length === 0) {
            context.isError = false;
            context[loadingKey] = false;
            context.searchString = '';
            context.partLookup = undefined;
            return;
        }
        context[loadingKey] = true;
        await new Promise(r => {
            scopedTimeoutRef = setTimeout(r, 1000);
            context.networkTimeoutRef = scopedTimeoutRef;
        });
        context.searchString = searchString;
        const partResponse = isSearchRequest ? await getPartLookup(context, { scopedTimeoutRef }) : newData;
        if (context.networkTimeoutRef === scopedTimeoutRef) {
            if (!partResponse)
                throw new Error('wrongResponseFormat');
            if (beforeAssignment)
                context.partLookup = await beforeAssignment(partResponse, { scopedTimeoutRef });
            else
                context.partLookup = partResponse;
            // Fire loadedResponse after partLookup is set to ensure consistent state
            // Only for search requests — DTO distribution should not re-trigger the callback chain
            if (isSearchRequest) {
                smartInvokable.bind(context)(context === null || context === void 0 ? void 0 : context.loadedResponse, partResponse);
            }
        }
        context.errorMessage = null;
        context[loadingKey] = false;
        context.isError = false;
    }
    catch (error) {
        if (error && (error === null || error === void 0 ? void 0 : error.name) === 'AbortError')
            return;
        smartInvokable.bind(context)(context.errorCallback, error.message);
        console.error(error);
        context.setErrorMessage(error.message);
    }
};
export const setPartLookupErrorState = (context, message) => {
    // @ts-ignore
    const loadingKey = (context === null || context === void 0 ? void 0 : context.localLoadingName) ? context === null || context === void 0 ? void 0 : context.localLoadingName : 'isLoading';
    context.isError = true;
    context[loadingKey] = false;
    context.errorMessage = message;
    context.partLookup = undefined;
};
export async function getPartLookup(context, generalProps) {
    const { scopedTimeoutRef } = generalProps;
    const handleResult = (newPartLookup) => {
        if ((context === null || context === void 0 ? void 0 : context.networkTimeoutRef) === scopedTimeoutRef) {
            if (!newPartLookup && (context === null || context === void 0 ? void 0 : context.searchString))
                throw new Error('wrongResponseFormat');
            return newPartLookup;
        }
    };
    if (context === null || context === void 0 ? void 0 : context.isDev) {
        const newData = context === null || context === void 0 ? void 0 : context.mockData[context === null || context === void 0 ? void 0 : context.searchString];
        return handleResult(newData);
    }
    else {
        if (!(context === null || context === void 0 ? void 0 : context.endpoint))
            throw new Error('noBaseUrl');
        const fetchConfig = { signal: context === null || context === void 0 ? void 0 : context.abortController.signal, additionalPath: '/' + context.searchString };
        const response = await fetchFrom(context.endpoint, fetchConfig);
        if (response.status === 204)
            throw new Error('noPartsFound');
        if (!response.ok)
            throw new Error('wildCard');
        const newData = (await response.json());
        return handleResult(newData);
    }
}
