import { jsx as _jsx } from "react/jsx-runtime";
import get from "lodash/get";
import merge from "lodash/merge";
import clone from "lodash/cloneDeep";
import { useMemo } from "react";
import { createContext, useContext } from "react";
import useAdaptiveImage from "../hooks/ui/useAdaptiveImage";
const Context = createContext(null);
function OneUIProvider({ children, config, }) {
    const prevCtx = useContext(Context);
    const scale = useAdaptiveImage();
    const mergedConfig = useMemo(() => {
        return merge(clone(prevCtx), config, {
            state: {
                imageScale: scale,
            },
        });
    }, [prevCtx, config, scale]);
    return _jsx(Context.Provider, { value: mergedConfig, children: children });
}
/**
 * The main provider component that wraps your app to enable UI features.
 */
export default OneUIProvider;
function pathToJson(path, key, exampleConfig = "THE_MISSING_CONFIG") {
    if (!key) {
        key = path.split(".").slice(-1)[0];
        path = path.replace(`.${key}`, "");
    }
    return path
        .split(".")
        .concat(key)
        .reduce((result, key, idx, arr) => {
        arr.slice(0, idx).reduce((r, k) => r[k], result)[key] =
            idx === arr.length - 1 ? exampleConfig : {};
        return result;
    }, {});
}
function ErrorWrapper(originalObject, path = "config") {
    return new Proxy(typeof originalObject !== "object" ? {} : originalObject || {}, {
        get(_target, key) {
            if (key === Symbol.toPrimitive || key === "$$typeof") {
                return () => _target[key];
            }
            try {
                const value = originalObject[key];
                if (typeof value === "undefined")
                    return undefined;
                if (typeof value === "object")
                    return ErrorWrapper(value, [path, key].filter(Boolean).join("."));
                return value;
            }
            catch (e) {
                const pathJson = pathToJson(path, key);
                throw new Error(`A component is using the UI config ${[path, key].join(".")}.

Please define it using:
import OneUIProvider from "@onepercent/one-ui/dist/context/OneUIProvider";

  ...
${`<OneUIProvider config={${JSON.stringify(pathJson, null, 4)}}>
...
</OneUIProvider>`.replace(/[ ]/g, "-")}`);
            }
        },
    });
}
/**
 * A hook to access the current UI configuration.
 */
export function useOneUIContext() {
    const context = useContext(Context);
    if (process.env.NODE_ENV === "development")
        return ErrorWrapper(context);
    return context;
}
/**
 * A hook to get a specific UI view component.
 */
export function useOneUIView(oneuiConfigPath, componentName) {
    const providedValue = useOneUIConfig(oneuiConfigPath);
    if (!providedValue) {
        throw new Error(`The component ${componentName} requires a view to be set on OneUI initialization

Views ready for use with this component shall be available at:
import SomeView from "@onepercentio/one-ui/dist/components/${componentName}/View/SomeView";

Please define it using:
import OneUIProvider from "@onepercentio/one-ui/dist/context/OneUIProvider";

  ...
${`<OneUIProvider config={${JSON.stringify(pathToJson(oneuiConfigPath, undefined, "SomeView"), null, 4)}}>
...
</OneUIProvider>`.replace(/[ ]/g, "-")}`);
    }
    return providedValue;
}
export function useOneUIConfig(prop, defaultValue) {
    const context = useContext(Context);
    if (process.env.NODE_ENV === "development") {
        const val = useMemo(() => {
            return get(context, prop);
        }, [context, prop]);
        if (typeof val === "string" ||
            typeof val === "function" ||
            prop.endsWith(".Component") ||
            prop.endsWith(".View"))
            return val || defaultValue;
        if (typeof val === "boolean")
            return val;
        return ErrorWrapper(val || defaultValue);
    }
    const value = useMemo(() => {
        return get(context, prop);
    }, [context, prop]);
    return value || defaultValue;
}
/**
 * A hook to get the current image scale setting.
 */
export function useCurrentImageScale() {
    const context = useContext(Context);
    return context.state.imageScale;
}
//# sourceMappingURL=OneUIProvider.js.map