import { useLynxGlobalEventListener } from '../../core/hooks/useLynxGlobalEventListener.js';
import { globalFlushOptions } from '../lifecycle/patch/commit.js';
// for better reuse if runtime is changed
export function factory({ createContext, useState, createElement, useLynxGlobalEventListener: useListener }, prop, eventName) {
    const Context = createContext({});
    const Provider = ({ children }) => {
        const [__, set] = useState(lynx[prop]);
        const handleChange = () => {
            if (prop === '__initData') {
                globalFlushOptions.triggerDataUpdated = true;
            }
            set(lynx[prop]);
        };
        useChanged(handleChange);
        return createElement(Context.Provider, {
            value: __,
        }, children);
    };
    const Consumer = Context.Consumer;
    const use = () => {
        const [__, set] = useState(lynx[prop]);
        useChanged(() => {
            if (prop === '__initData') {
                globalFlushOptions.triggerDataUpdated = true;
            }
            set(lynx[prop]);
        });
        return __;
    };
    const useChanged = (callback) => {
        if (!__LEPUS__) {
            useListener(eventName, callback);
        }
    };
    return {
        /* v8 ignore next */
        Context: () => Context,
        Provider: () => Provider,
        Consumer: () => Consumer,
        use: () => use,
        useChanged: () => useChanged,
    };
}
/**
 * Higher-Order Component (HOC) that injects `initData` into the state of the given class component.
 *
 * This HOC checks if the provided component is a class component. If it is, it wraps the component
 * and injects the `initData` into its state. It also adds a listener
 * to update the state when data changes, and removes the listener when the component unmounts.
 *
 * @typeParam P - The type of the props of the wrapped component.
 * @typeParam S - The type of the state of the wrapped component.
 *
 * @param App - The class component to be wrapped by the HOC.
 *
 * @returns The original component if it is not a class component, otherwise a new class component
 *          with `initData` injection and state update functionality.
 *
 * @example
 * ```typescript
 * class App extends React.Component<MyProps, MyState> {
 *   // component implementation
 * }
 *
 * export default withInitDataInState(App);
 * ```
 * @public
 */
export function withInitDataInState(App) {
    const isClassComponent = 'prototype' in App && 'render' in App.prototype;
    /* v8 ignore next 4 */
    if (!isClassComponent) {
        // return as-is when not class component
        return App;
    }
    class C extends App {
        h;
        constructor(props) {
            super(props);
            this.state = {
                ...this.state,
                ...lynx.__initData,
            };
            if (!__LEPUS__) {
                lynx.getJSModule('GlobalEventEmitter').addListener('onDataChanged', this.h = (...args) => {
                    const [newData] = args;
                    globalFlushOptions.triggerDataUpdated = true;
                    this.setState(newData);
                });
            }
        }
        componentWillUnmount() {
            super.componentWillUnmount?.();
            if (!__LEPUS__) {
                lynx.getJSModule('GlobalEventEmitter').removeListener('onDataChanged', this.h);
            }
        }
    }
    return C;
}
//# sourceMappingURL=initData.js.map