import { Emitter } from '@opensumi/ide-core-common';
import { useEffect, useRef, useState } from 'react';
const get = (obj, path) => {
    let index = 0;
    const length = path.length;
    while (obj != null && index < length) {
        obj = obj[path[index++]];
    }
    return index && index == length ? obj : undefined;
};
export const IPropsService = Symbol('IPropsService');
export class PropsServiceImpl {
    constructor() {
        this._onPropsChange = new Emitter();
        this.onPropsChange = this._onPropsChange.event;
    }
    get props() {
        return this._props;
    }
    set props(nextProps) {
        const prevProps = this._props;
        this._props = nextProps;
        this._firePropsChange(this._props, prevProps);
    }
    _firePropsChange(props, prevProps) {
        this._onPropsChange.fire({
            prevProps,
            props,
            affect(...keys) {
                return get(props, keys) !== get(prevProps, keys);
            },
        });
    }
}
const refEquality = (a, b) => a === b;
function usePropsSelector(service, selector, isEqual = refEquality) {
    const lastSelector = useRef(selector);
    lastSelector.current = selector;
    const [selectedState, setSelectedState] = useState(() => {
        const state = service.props;
        return lastSelector.current ? lastSelector.current(state) : state;
    });
    const lastSelectedState = useRef(selectedState);
    lastSelectedState.current = selectedState;
    useEffect(() => {
        const disposer = service.onPropsChange(() => {
            try {
                if (lastSelector.current) {
                    const newSelectedState = lastSelector.current(service.props);
                    if (!isEqual(newSelectedState, lastSelectedState.current)) {
                        lastSelectedState.current = newSelectedState;
                        // 防止 newSelectedState 是函数，例如组件，这时直接传回被当做函数执行
                        setSelectedState(() => newSelectedState);
                    }
                }
                else {
                    setSelectedState(() => service.props);
                }
            }
            catch (err) {
                console.error('dispatch handler error', err);
            }
        });
        return () => {
            disposer.dispose();
        };
    }, []);
    return selectedState;
}
export { usePropsSelector };
//# sourceMappingURL=props.service.js.map