import copy from "copy-to-clipboard";
import { useCallback, useEffect, useState, useMemo, } from "react";
export const useClickOutside = (ref, onClickOutsideClick) => {
    useEffect(() => {
        const iframes = Array.from(document.querySelectorAll("iframe"))
            .filter((node) => {
            try {
                return node?.contentWindow?.document;
            }
            catch (e) {
                if (e instanceof DOMException) {
                    /** ignore this error */
                }
                else if (e instanceof Error) {
                    console.error(e.message);
                }
                return false;
            }
        })
            .map((node) => node?.contentWindow?.document)
            .filter((v) => !!v);
        const listenerNodes = [document, ...iframes];
        const handleClickOutside = (event) => {
            if (ref &&
                ref.current &&
                event &&
                !ref.current.contains(event.target)) {
                onClickOutsideClick();
            }
        };
        listenerNodes.forEach((node) => node.addEventListener("click", handleClickOutside));
        return () => {
            listenerNodes.forEach((node) => node.removeEventListener("click", handleClickOutside));
        };
    }, [ref, onClickOutsideClick]);
};
/**@deprecated this hook is broken and should be removed */
export const useScrollOutside = (ref, onScrollOutside, scrollElement, enabled, isOpen) => {
    useEffect(() => {
        const element = scrollElement ?? document;
        const handleScroll = () => {
            onScrollOutside();
            element.removeEventListener("scroll", handleScroll);
        };
        if (isOpen && enabled) {
            element.addEventListener("scroll", handleScroll);
        }
        return () => {
            element.removeEventListener("scroll", handleScroll);
        };
    }, [isOpen, enabled]);
};
/** @deprecated */
export const useCopy = (message, sendMessage) => {
    return useCallback(() => {
        copy(message);
        sendMessage && sendMessage();
    }, [message, sendMessage]);
};
const defaultParsePayload = (text) => {
    const json = JSON.parse(text);
    if (!json?.success) {
        throw new Error(// TODO error text
        json?.status ? `error code: ${json.status}` : "Unknown error");
    }
    const { payload } = json;
    return payload;
};
export const useFetch = ({ query, predicate, headers, method, parsePayload, }, needsUpdate = true) => {
    const [data, setData] = useState();
    const [error, setError] = useState();
    const [pending, setPending] = useState(false);
    const exec = useCallback(async (body, queryParams) => {
        if (!query) {
            setData(undefined);
        }
        else {
            let queryParamsStr = "";
            if (queryParams) {
                for (let key in queryParams) {
                    queryParamsStr += queryParamsStr.length > 0 ? "&" : "?";
                    queryParamsStr += `${key}=${queryParams[key]}`;
                }
            }
            let text;
            try {
                setPending(true);
                const response = await fetch(query + queryParamsStr, {
                    method: method ?? "get",
                    headers,
                    body,
                });
                text = await response.text();
                const payload = (parsePayload ?? defaultParsePayload)(text);
                if (predicate(payload)) {
                    setData(payload);
                    return payload;
                }
                else {
                    throw new Error("wrong data");
                }
            }
            catch (e) {
                let msg = text;
                if (e instanceof Error) {
                    console.error(`Error while fetching ${query}`, e.message);
                    if (!msg) {
                        msg = e.message;
                    }
                }
                setError(new Error(msg));
            }
            finally {
                setPending(false);
            }
        }
    }, [query, predicate, method, headers]);
    useEffect(() => {
        if (needsUpdate) {
            const timeout = setTimeout(async () => {
                await exec();
            }, 150);
            return () => {
                clearTimeout(timeout);
            };
        }
    }, [exec, needsUpdate]);
    return { data, error, pending, exec };
};
export const useStored = (name, storage = globalThis.localStorage) => {
    const initialValue = useMemo(() => {
        return storage?.getItem(name) ?? undefined;
    }, [name, storage]);
    const [data, setData] = useState(initialValue);
    useEffect(() => {
        const value = storage?.getItem(name);
        if (value !== null) {
            setData(value);
        }
    }, [name, storage]);
    const set = useCallback((value) => {
        storage?.setItem(name, value);
        setData(value);
    }, [name, storage]);
    const remove = useCallback(() => {
        storage?.removeItem(name);
        setData(undefined);
    }, [name, storage]);
    return { data, set, remove };
};
//# sourceMappingURL=common.js.map