/**
 * DevExtreme (esm/renovation/utils/plugin/context.js)
 * Version: 22.1.3 (build 22180-0310)
 * Build date: Wed Jun 29 2022
 *
 * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
 * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
 */
import {
    createContext
} from "@devextreme/runtime/inferno";
var nextEntityId = 1;
export class PluginEntity {
    constructor() {
        this.id = nextEntityId;
        nextEntityId += 1
    }
    getValue(value, _plugins) {
        return value
    }
}
export class PluginGetter extends PluginEntity {
    constructor(defaultValue) {
        super();
        this.defaultValue = defaultValue
    }
    getValue(value, plugins) {
        if (!value) {
            return this.defaultValue
        }
        return value.reduce((base, item) => {
            if (plugins && item.deps) {
                var hasValues = item.deps.every(entity => plugins.hasValue(entity));
                if (!hasValues) {
                    return base
                }
                var args = item.deps.map(entity => {
                    if (entity.id === this.id) {
                        return base
                    }
                    return plugins.getValue(entity)
                });
                return item.func.apply(null, args)
            }
            return item.func(base)
        }, this.defaultValue)
    }
}
export class PluginSelector extends PluginEntity {
    constructor(deps, func) {
        super();
        this.deps = deps;
        this.func = func
    }
}
export function createValue() {
    return new PluginEntity
}
export function createSelector(deps, func) {
    return new PluginSelector(deps, func)
}
export function createGetter(defaultValue) {
    return new PluginGetter(defaultValue)
}
export function createPlaceholder() {
    return new PluginEntity
}

function createUnsubscribeFunction(childSubscriptionsList, subscription) {
    return () => {
        childSubscriptionsList.forEach(childSubscriptions => {
            var index = childSubscriptions.indexOf(subscription);
            if (index >= 0) {
                childSubscriptions.splice(index, 1)
            }
        })
    }
}
export class Plugins {
    constructor() {
        this.items = {};
        this.subscriptions = {};
        this.subscribedSelectors = {}
    }
    set(entity, value) {
        var force = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : false;
        if (entity.id in this.items && this.items[entity.id] === value && !force) {
            return
        }
        this.items[entity.id] = value;
        this.fireSubscriptions(entity)
    }
    fireSubscriptions(entity) {
        var value = this.items[entity.id];
        var subscriptions = this.subscriptions[entity.id];
        if (subscriptions) {
            var callbackValue = entity.getValue(value, this);
            subscriptions.forEach(handler => {
                handler(callbackValue)
            })
        }
    }
    extend(entity, order, func, deps) {
        var value = this.items[entity.id] || [];
        var insertIndex = value.filter(item => item.order < order).length;
        var item = {
            order: order,
            func: func,
            deps: deps
        };
        var unsubscribe = deps ? this.subscribeToGetterItemDeps(entity, deps) : void 0;
        value.splice(insertIndex, 0, item);
        this.set(entity, value, true);
        return () => {
            var index = value.indexOf(item);
            if (index >= 0) {
                value.splice(index, 1);
                null === unsubscribe || void 0 === unsubscribe ? void 0 : unsubscribe();
                this.set(entity, value, true)
            }
        }
    }
    extendPlaceholder(entity, order, component) {
        var deps = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : [];
        var value = this.items[entity.id] || [];
        var insertIndex = value.filter(item => item.order < order).length;
        var item = {
            order: order,
            component: component,
            deps: deps
        };
        value.splice(insertIndex, 0, item);
        this.set(entity, value, true);
        return () => {
            var index = value.indexOf(item);
            if (index >= 0) {
                value.splice(index, 1);
                this.set(entity, value, true)
            }
        }
    }
    getValue(entity) {
        this.update(entity);
        var value = this.items[entity.id];
        return entity.getValue(value, this)
    }
    hasValue(entity) {
        if (entity instanceof PluginGetter) {
            return true
        }
        return entity.id in this.items
    }
    updateSelectorValue(entity) {
        var childValues = entity.deps.map(childEntity => this.getValue(childEntity));
        var newValue = entity.func.apply(null, childValues);
        this.set(entity, newValue)
    }
    subscribeToSelectorDeps(entity) {
        if (!this.subscribedSelectors[entity.id]) {
            this.subscribedSelectors[entity.id] = true;
            entity.deps.forEach(childEntity => {
                var childSubscriptions = this.getSubscriptions(childEntity);
                childSubscriptions.push(() => {
                    this.update(entity, true)
                })
            })
        }
    }
    subscribeToGetterItemDeps(getter, deps) {
        var fireEntitySubscriptions = () => this.fireSubscriptions(getter);
        var childSubscriptionsList = deps.filter(childEntity => childEntity.id !== getter.id).map(childEntity => this.getSubscriptions(childEntity));
        childSubscriptionsList.forEach(childSubscriptions => {
            childSubscriptions.push(fireEntitySubscriptions)
        });
        return createUnsubscribeFunction(childSubscriptionsList, fireEntitySubscriptions)
    }
    updateSelector(entity) {
        entity.deps.forEach(child => {
            this.update(child)
        });
        this.subscribeToSelectorDeps(entity);
        if (entity.deps.every(childEntity => this.hasValue(childEntity))) {
            this.updateSelectorValue(entity)
        }
    }
    update(entity) {
        var force = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : false;
        if (entity instanceof PluginSelector) {
            if (!this.hasValue(entity) || force) {
                this.updateSelector(entity)
            }
        }
    }
    getSubscriptions(entity) {
        var subscriptions = this.subscriptions[entity.id] || [];
        this.subscriptions[entity.id] = subscriptions;
        return subscriptions
    }
    watch(entity, callback) {
        this.update(entity);
        if (this.hasValue(entity)) {
            var value = this.items[entity.id];
            var callbackValue = entity.getValue(value, this);
            callback(callbackValue)
        }
        var subscriptions = this.getSubscriptions(entity);
        subscriptions.push(callback);
        return () => {
            var index = subscriptions.indexOf(callback);
            if (index >= 0) {
                subscriptions.splice(index, 1)
            }
        }
    }
    callAction(entity) {
        var value = this.getValue(entity);
        for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
            args[_key - 1] = arguments[_key]
        }
        return null === value || void 0 === value ? void 0 : value(...args)
    }
}
export var PluginsContext = createContext(null);
