import { useEffect, useMemo, useState } from 'react';
import mitt from 'mitt';
import { useEvent } from './event';
const storage = new (class Storage {
    constructor() {
        this.emitter = mitt();
        window.addEventListener('storage', (event) => {
            if (event.key == null) {
                this.emitter.emit('clear');
                return;
            }
            if (event.oldValue !== event.newValue) {
                let value;
                try {
                    value = JSON.parse(event.newValue || '');
                }
                catch (error) {
                    value = event.newValue;
                }
                event.key && this.emit(event.key, value);
            }
        });
    }
    emit(key, value) {
        this.emitter.emit(key, value);
    }
    subscribe(key, callback) {
        this.emitter.on(key, callback);
    }
    unsubscribe(key, callback) {
        this.emitter.off(key, callback);
    }
    onClear(callback) {
        this.emitter.on('clear', callback);
    }
    onClearUnsubscribe(callback) {
        this.emitter.off('clear', callback);
    }
    setItem(key, value) {
        if (value === undefined) {
            localStorage.removeItem(key);
        }
        else {
            const data = JSON.stringify(value);
            localStorage.setItem(key, data);
        }
        this.emit(key, value);
    }
    getItem(key, defaultValue) {
        try {
            const data = localStorage.getItem(key);
            const parsed = typeof data === 'string' ? JSON.parse(data) : undefined;
            if (typeof defaultValue === 'function') {
                return defaultValue(parsed);
            }
            return parsed !== undefined ? parsed : defaultValue;
        }
        catch (error) {
            return typeof defaultValue === 'function' ? defaultValue(null) : defaultValue;
        }
    }
    removeItem(key) {
        this.setItem(key, undefined);
    }
})();
export function useLocalStorage(key, defaultValue) {
    const getter = () => storage.getItem(key, defaultValue);
    const [value, setValue] = useState(getter);
    useEffect(() => {
        setValue(getter);
        storage.subscribe(key, (value) => {
            // @ts-ignore
            setValue(typeof defaultValue === 'function' ? defaultValue(value) : (value ?? defaultValue));
        });
        return () => {
            storage.unsubscribe(key, setValue);
        };
    }, [key]);
    const handleClear = useEvent(() => {
        // @ts-ignore
        setValue(() => null);
    });
    useEffect(() => {
        storage.onClear(handleClear);
        return () => {
            return storage.onClearUnsubscribe(handleClear);
        };
    }, [key]);
    return useMemo(() => {
        function setItem(next) {
            storage.setItem(key, next);
            return next;
        }
        function removeItem() {
            storage.removeItem(key);
        }
        return [value, setItem, removeItem];
    }, [key, value]);
}
//# sourceMappingURL=local-storage.js.map