import { useState, useEffect } from 'react';
import { hasCurrentClient, load, reload } from '../main';
import { InfinityMintClient } from '../client';
import WebEvents from '../webEvents';
import { Project } from '../core/project';
import { Dictionary } from 'infinitymint/dist/app/helpers';
import { InfinityMintClientConfig } from '../core/interfaces';

let hasLoaded = false;
let isLoading = false;
const loadClient = async (config: InfinityMintClientConfig) => {
    if (isLoading) return;
    isLoading = true;

    if (hasLoaded) return;
    if (hasCurrentClient()) return;

    (globalThis as any).process = globalThis.process || {};
    (globalThis as any).process.env = (globalThis as any).process.env || {};
    (globalThis as any).process.env = {
        ...(globalThis as any).process.env,
        ...(config.env || {}),
    };

    let client = load(config);
    return client;
};

const useClientContext = ({ config }: { config: InfinityMintClientConfig }) => {
    const [loaded, setLoaded] = useState(false);
    const [controller, setController] = useState<InfinityMintClient>(null);
    const [project, setProject] = useState<Project>(null);
    const [projects, setProjects] = useState<Dictionary<Project>>({});
    const [error, setError] = useState(null);
    const [admin, setAdmin] = useState(false);

    useEffect(() => {
        setError(null);
        setLoaded(false);

        (async () => {
            let client = await loadClient(config);
            if (!client) return; //already loaded

            setController(client);
            setProject(client.defaultProject);
            setProjects(client.projects);

            if (client.web3Access && client.networkAccess)
                setAdmin(await client.defaultProject.isAdmin());
        })()
            .catch((err) => {
                setError(err);
            })
            .finally(() => {
                setLoaded(true);
            });

        let cb = async () => {
            setError(null);
            setLoaded(false);

            try {
                let client = await reload(config);
                setController(client);
                setProject(client.defaultProject);
                setProjects(client.projects);

                if (client.web3Access && client.networkAccess)
                    setAdmin(await client.defaultProject.isAdmin());
            } catch (error) {
                setError(error);
            } finally {
                setLoaded(true);
            }
        };

        WebEvents.on('reload', cb);

        return () => {
            WebEvents.off('reload', cb);
        };
    }, [config]);

    return {
        loaded,
        controller,
        error,
        project,
        projects,
        admin,
    };
};

export default useClientContext;
