import { get, getImmutable, findIndexByKey, getCommonPath, } from './utils';
export class Store {
    constructor(data) {
        this.data = data;
        this.listeners = [];
    }
    get(path) {
        return get(this.data, path);
    }
    set(path, value) {
        const item = getImmutable(this.data, path.slice(0, -1), this, 'data');
        if (typeof item !== 'object' || item === null) {
            return;
        }
        const key = path.at(-1);
        if (Array.isArray(item)) {
            const index = findIndexByKey(item, key);
            if (index !== -1) {
                item[index] = value;
            }
        }
        else {
            item[key] = value;
        }
        this.listeners.forEach((listener) => listener(path, value));
    }
    delete(path) {
        const item = getImmutable(this.data, path.slice(0, -1), this, 'data');
        if (typeof item !== 'object' || item === null) {
            return;
        }
        const key = path.at(-1);
        if (Array.isArray(item)) {
            const index = findIndexByKey(item, key);
            if (index !== -1) {
                item.splice(index, 1);
            }
        }
        else {
            delete item[key];
        }
        this.listeners.forEach((listener) => listener(path));
    }
    deleteByPaths(paths) {
        if (!paths.length) {
            return;
        }
        const commonPath = getCommonPath(paths);
        // Go one level upper to avoid issue when common path points to object in array
        commonPath.pop();
        const subRoot = getImmutable(this.data, commonPath, this, 'data');
        if (!subRoot) {
            return;
        }
        for (const path of paths) {
            const item = getImmutable(subRoot, path.slice(commonPath.length, -1));
            if (typeof item !== 'object' || item === null) {
                continue;
            }
            const key = path.at(-1);
            if (Array.isArray(item)) {
                const index = findIndexByKey(item, key);
                if (index !== -1) {
                    item.splice(index, 1);
                }
            }
            else {
                delete item[key];
            }
        }
        this.listeners.forEach((listener) => listener(commonPath, subRoot));
    }
    subscribe(listener) {
        this.listeners.push(listener);
        return () => {
            this.listeners = this.listeners.filter((currentListener) => currentListener !== listener);
        };
    }
}
