import { useState, useReducer, useEffect, useMemo } from "react";
import { useSortedFilteredApps } from "./filtering";
import { reducer, initState, getNextAppOp, isOutOfMemoryState, predictOptimisticState, } from "./logic";
import { runAppOp } from "./runner";
import { useFeatureFlags } from "../featureFlags";
// use for React apps. support dynamic change of the state.
export const useAppsRunner = (listResult, exec, appsToRestore) => {
    // $FlowFixMe for ledger-live-mobile older react/flow version
    const [state, dispatch] = useReducer(reducer, null, () => initState(listResult, appsToRestore));
    const nextAppOp = useMemo(() => getNextAppOp(state), [state]);
    const appOp = state.currentAppOp || nextAppOp;
    useEffect(() => {
        dispatch({
            type: "reset",
            initialState: initState(listResult, appsToRestore),
        });
    }, [listResult, appsToRestore]);
    useEffect(() => {
        if (appOp) {
            const sub = runAppOp({ state, appOp, exec }).subscribe(event => {
                dispatch({
                    type: "onRunnerEvent",
                    event,
                });
            });
            return () => {
                sub.unsubscribe();
            };
        } // we only want to redo the effect on appOp changes here
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [listResult, appOp, exec]);
    return [state, dispatch];
};
export function useNotEnoughMemoryToInstall(state, name) {
    return useMemo(() => isOutOfMemoryState(predictOptimisticState(reducer(state, {
        type: "install",
        name,
    }))), [name, state]);
}
export function useAppsSections(state, opts) {
    const { updateAllQueue, appByName, installed, installQueue, apps } = state;
    const appsUpdating = useMemo(() => updateAllQueue.map(name => appByName[name]).filter(Boolean), [appByName, updateAllQueue]);
    const updatableAppList = useMemo(() => apps.filter(({ name }) => installed.some(i => i.name === name && !i.updated)), [apps, installed]);
    const { getFeature, isFeature } = useFeatureFlags();
    const update = appsUpdating.length > 0 ? appsUpdating : updatableAppList;
    const filterParam = useMemo(() => ({
        query: opts.query,
        installedApps: installed,
        type: [opts.appFilter],
        getFeature,
        isFeature,
    }), [getFeature, installed, isFeature, opts.appFilter, opts.query]);
    const catalog = useSortedFilteredApps(apps, filterParam, opts.sort);
    const installedAppList = useSortedFilteredApps(apps, {
        query: opts.query,
        installedApps: installed,
        installQueue,
        type: ["installed"],
        getFeature,
        isFeature,
    }, {
        type: "default",
        order: "asc",
    });
    const device = installedAppList.sort(({ name: _name }, { name }) => {
        // place install queue on top of list
        // with the app being installed at the top
        let pos1 = installQueue.indexOf(_name);
        let pos2 = installQueue.indexOf(name);
        pos1 = pos1 < 0 ? Number.MAX_VALUE : pos1;
        pos2 = pos2 < 0 ? Number.MAX_VALUE : pos2;
        return pos1 - pos2;
    });
    return {
        update,
        catalog,
        device,
    };
}
export function useAppInstallProgress(state, name) {
    const { currentProgressSubject, currentAppOp } = state;
    const [progress, setProgress] = useState(0);
    useEffect(() => {
        if (!currentAppOp || !currentProgressSubject || currentAppOp.name !== name) {
            setProgress(0);
            return;
        }
        const sub = currentProgressSubject.subscribe(setProgress);
        return () => sub.unsubscribe();
    }, [currentProgressSubject, currentAppOp, name]);
    if (currentProgressSubject && currentAppOp && currentAppOp.name === name) {
        return progress;
    }
    return 0;
}
// if the app needs deps to be installed, we want to display a modal
// this should returns all params the modal also need (so we don't do things twice)
export function useAppInstallNeedsDeps(state, app) {
    const { appByName, installed: installedList, installQueue } = state;
    const res = useMemo(() => {
        const dependencies = (app.dependencies || [])
            .map(name => appByName[name])
            .filter(dep => dep &&
            !installedList.some(app => app.name === dep.name) &&
            !installQueue.includes(dep.name));
        if (dependencies.length) {
            return {
                app,
                dependencies,
            };
        }
        return null;
    }, [appByName, app, installQueue, installedList]);
    return res;
}
// if the app needs deps to be installed, we want to display a modal
// this should returns all params the modal also need (so we don't do things twice)
export function useAppUninstallNeedsDeps(state, app) {
    const { apps, installed } = state;
    const res = useMemo(() => {
        const dependents = apps.filter(a => installed.some(i => i.name === a.name) && a.dependencies.includes(app.name));
        if (dependents.length) {
            return {
                dependents,
                app,
            };
        }
        return null;
    }, [app, apps, installed]);
    return res;
}
//# sourceMappingURL=react.js.map