import { __extends, __values } from "tslib";
import { IgcHTMLElement } from "./igc-html-element";
var IgcPortalItemComponent = /** @class */ /*@__PURE__*/ (function (_super) {
    __extends(IgcPortalItemComponent, _super);
    function IgcPortalItemComponent() {
        var _this = _super.call(this) || this;
        _this._portalId = 0;
        _this._portalId = IgcPortalItemComponent._nextPortalId;
        IgcPortalItemComponent._nextPortalId += 1;
        return _this;
    }
    Object.defineProperty(IgcPortalItemComponent.prototype, "portalId", {
        get: function () {
            return this._portalId;
        },
        enumerable: false,
        configurable: true
    });
    IgcPortalItemComponent.prototype.connectedCallback = function () {
        if (this.parentElement) {
            if (this.parentElement instanceof IgcPortalEntranceComponent) {
                var entrance = this.parentElement;
                entrance.ensurePortalUpdated();
            }
        }
    };
    IgcPortalItemComponent._nextPortalId = 0;
    return IgcPortalItemComponent;
}(IgcHTMLElement));
export { IgcPortalItemComponent };
var IgcPortalEntranceComponent = /** @class */ /*@__PURE__*/ (function (_super) {
    __extends(IgcPortalEntranceComponent, _super);
    function IgcPortalEntranceComponent() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this._detach = null;
        _this._observer = null;
        _this._suspendChangeDetection = false;
        _this._itemContent = new Map();
        return _this;
    }
    Object.defineProperty(IgcPortalEntranceComponent.prototype, "portalId", {
        get: function () {
            return this.getAttribute("portal-id");
        },
        set: function (value) {
            this.setAttribute("portal-id", value);
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(IgcPortalEntranceComponent.prototype, "useShadowMode", {
        get: function () {
            return this.getAttribute("use-shadow-mode") == "true";
        },
        set: function (value) {
            this.setAttribute("use-shadow-mode", value ? "true" : "false");
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(IgcPortalEntranceComponent.prototype, "moveOnceMode", {
        get: function () {
            return this.getAttribute("move-once-mode") == "true";
        },
        set: function (value) {
            this.setAttribute("move-once-mode", value ? "true" : "false");
        },
        enumerable: false,
        configurable: true
    });
    IgcPortalEntranceComponent.prototype.connectedCallback = function () {
        var _this = this;
        this._detach = PortalChannel.instance().subscribe(this.portalId, function (m) { return _this.onPortalMessage(m); });
        PortalChannel.instance().broadcast(PortalMessage.entranceAttaching(this, this.portalId, this.useShadowMode));
        if (this.useShadowMode) {
        }
        else {
            this._observer = new MutationObserver(function (mutations) {
                if (!_this._suspendChangeDetection) {
                    _this.ensurePortalUpdated();
                }
            });
            this._observer.observe(this, { childList: true, subtree: true });
        }
        this.ensurePortalUpdated();
    };
    IgcPortalEntranceComponent.prototype.getPortalContent = function () {
        var e_1, _a, e_2, _b;
        var useMoveOnce = this.moveOnceMode;
        var children = Array.from(this.children);
        var items = children.filter(function (c) { return c instanceof IgcPortalItemComponent; });
        if (useMoveOnce) {
            items = children;
        }
        var ret = [];
        var seen = new Set();
        for (var i = 0; i < items.length; i++) {
            var currItem = items[i];
            var prevContent = null;
            if (!useMoveOnce) {
                var portalItem = currItem;
                seen.add(portalItem.portalId);
                if (this._itemContent.has(portalItem.portalId)) {
                    prevContent = this._itemContent.get(portalItem.portalId);
                }
            }
            var itemChild = useMoveOnce ? currItem : (currItem.children.length > 0 ? currItem.children[0] : null);
            if (!useMoveOnce) {
                var portalItem = currItem;
                if (itemChild && itemChild != prevContent) {
                    this._itemContent.set(portalItem.portalId, itemChild);
                }
                else {
                    itemChild = prevContent;
                }
                if (itemChild) {
                    itemChild.___portalItemId = portalItem.portalId;
                }
            }
            if (itemChild) {
                ret.push(itemChild);
            }
        }
        var toRemove = [];
        try {
            for (var _c = __values(this._itemContent.keys()), _d = _c.next(); !_d.done; _d = _c.next()) {
                var key = _d.value;
                if (!seen.has(key)) {
                    toRemove.push(key);
                }
            }
        }
        catch (e_1_1) {
            e_1 = { error: e_1_1 };
        }
        finally {
            try {
                if (_d && !_d.done && (_a = _c.return))
                    _a.call(_c);
            }
            finally {
                if (e_1)
                    throw e_1.error;
            }
        }
        try {
            for (var toRemove_1 = __values(toRemove), toRemove_1_1 = toRemove_1.next(); !toRemove_1_1.done; toRemove_1_1 = toRemove_1.next()) {
                var key = toRemove_1_1.value;
                this._itemContent.delete(key);
            }
        }
        catch (e_2_1) {
            e_2 = { error: e_2_1 };
        }
        finally {
            try {
                if (toRemove_1_1 && !toRemove_1_1.done && (_b = toRemove_1.return))
                    _b.call(toRemove_1);
            }
            finally {
                if (e_2)
                    throw e_2.error;
            }
        }
        return ret;
    };
    IgcPortalEntranceComponent.prototype.ensurePortalUpdated = function () {
        this._suspendChangeDetection = true;
        PortalChannel.instance().broadcast(PortalMessage.entranceSlotContentUpdated(this, this.portalId, this.getPortalContent()));
        this._suspendChangeDetection = false;
    };
    IgcPortalEntranceComponent.prototype.disconnectedCallback = function () {
        PortalChannel.instance().broadcast(PortalMessage.entranceDetaching(this, this.portalId));
        if (this._detach) {
            this._detach();
        }
        if (this.useShadowMode) {
        }
        else {
            if (this._observer) {
                this._observer.disconnect();
                this._observer = null;
            }
        }
    };
    IgcPortalEntranceComponent.prototype.onPortalMessage = function (m) {
        if (m.sender === this) {
            return;
        }
        if (m.portalId == this.portalId) {
            switch (m.messageType) {
                case PortalMessageType.ExitAttaching:
                    this.ensurePortalUpdated();
                    break;
            }
        }
    };
    return IgcPortalEntranceComponent;
}(IgcHTMLElement));
export { IgcPortalEntranceComponent };
var IgcPortalExitComponent = /** @class */ /*@__PURE__*/ (function (_super) {
    __extends(IgcPortalExitComponent, _super);
    function IgcPortalExitComponent() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this._detach = null;
        return _this;
    }
    Object.defineProperty(IgcPortalExitComponent.prototype, "portalId", {
        get: function () {
            return this.getAttribute("portal-id");
        },
        set: function (value) {
            this.setAttribute("portal-id", value);
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(IgcPortalExitComponent.prototype, "useShadowMode", {
        get: function () {
            return this.getAttribute("use-shadow-mode") == "true";
        },
        set: function (value) {
            this.setAttribute("use-shadow-mode", value ? "true" : "false");
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(IgcPortalExitComponent.prototype, "useParentAsTarget", {
        get: function () {
            return this.getAttribute("use-parent-as-target") == "true";
        },
        set: function (value) {
            this.setAttribute("use-parent-as-target", value ? "true" : "false");
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(IgcPortalExitComponent.prototype, "moveOnceMode", {
        get: function () {
            return this.getAttribute("move-once-mode") == "true";
        },
        set: function (value) {
            this.setAttribute("move-once-mode", value ? "true" : "false");
        },
        enumerable: false,
        configurable: true
    });
    IgcPortalExitComponent.prototype.connectedCallback = function () {
        var _this = this;
        this._detach = PortalChannel.instance().subscribe(this.portalId, function (m) { return _this.onPortalMessage(m); });
        PortalChannel.instance().broadcast(PortalMessage.exitAttaching(this, this.portalId, this.useShadowMode));
    };
    IgcPortalExitComponent.prototype.disconnectedCallback = function () {
        PortalChannel.instance().broadcast(PortalMessage.exitDetaching(this, this.portalId));
        if (this._detach) {
            this._detach();
        }
    };
    IgcPortalExitComponent.prototype.onPortalMessage = function (m) {
        if (m.sender === this) {
            return;
        }
        if (m.portalId == this.portalId) {
            switch (m.messageType) {
                case PortalMessageType.EntranceSlotContentUpdated:
                    this.onSlotContentChanging(m);
                    break;
            }
        }
    };
    IgcPortalExitComponent.prototype.onSlotContentChanging = function (m) {
        var useMoveOnce = this.moveOnceMode;
        if (this.useShadowMode) {
        }
        else {
            var target = this;
            if (this.useParentAsTarget && this.parentElement) {
                target = this.parentElement;
            }
            if (!useMoveOnce) {
                for (var i = target.children.length - 1; i >= 0; i--) {
                    if (target.children[i] === this) {
                        continue;
                    }
                    target.children[i].remove();
                }
            }
            if (m.content) {
                var arr = m.content;
                for (var i = 0; i < arr.length; i++) {
                    target.append(arr[i]);
                }
            }
        }
    };
    return IgcPortalExitComponent;
}(IgcHTMLElement));
export { IgcPortalExitComponent };
var PortalChannel = /** @class */ /*@__PURE__*/ (function () {
    function PortalChannel() {
        this._subscribers = new Map();
    }
    PortalChannel.instance = function () {
        if (this._instance == null) {
            this._instance = new PortalChannel();
        }
        return this._instance;
    };
    PortalChannel.prototype.subscribe = function (portalId, onMessage) {
        var _this = this;
        if (!this._subscribers.has(portalId)) {
            this._subscribers.set(portalId, []);
        }
        this._subscribers.get(portalId).push(onMessage);
        return function () {
            if (_this._subscribers.has(portalId)) {
                var ind = _this._subscribers.get(portalId).indexOf(onMessage);
                _this._subscribers.get(portalId).splice(ind, 1);
                if (_this._subscribers.get(portalId).length == 0) {
                    _this._subscribers.delete(portalId);
                }
            }
        };
    };
    PortalChannel.prototype.broadcast = function (m) {
        if (!this._subscribers.has(m.portalId)) {
            return;
        }
        var subs = this._subscribers.get(m.portalId).slice();
        for (var i = 0; i < subs.length; i++) {
            subs[i](m);
        }
    };
    PortalChannel._instance = null;
    return PortalChannel;
}());
var PortalMessageType = /*@__PURE__*/ (function (PortalMessageType) {
    PortalMessageType[PortalMessageType["EntranceAttaching"] = 0] = "EntranceAttaching";
    PortalMessageType[PortalMessageType["EntranceDetaching"] = 1] = "EntranceDetaching";
    PortalMessageType[PortalMessageType["ExitAttaching"] = 2] = "ExitAttaching";
    PortalMessageType[PortalMessageType["ExitDetaching"] = 3] = "ExitDetaching";
    PortalMessageType[PortalMessageType["EntranceSlotContentUpdated"] = 4] = "EntranceSlotContentUpdated";
    return PortalMessageType;
})({});
var PortalMessage = /** @class */ /*@__PURE__*/ (function () {
    function PortalMessage() {
        this.useShadowMode = false;
        this.messageType = PortalMessageType.EntranceAttaching;
        this.portalId = "";
        this.content = null;
        this.sender = null;
    }
    PortalMessage.entranceAttaching = function (sender, portalId, useShadowMode) {
        var m = new PortalMessage();
        m.messageType = PortalMessageType.EntranceAttaching;
        m.sender = sender;
        m.portalId = portalId;
        m.useShadowMode = useShadowMode;
        return m;
    };
    PortalMessage.entranceDetaching = function (sender, portalId) {
        var m = new PortalMessage();
        m.messageType = PortalMessageType.EntranceDetaching;
        m.sender = sender;
        m.portalId = portalId;
        return m;
    };
    PortalMessage.exitAttaching = function (sender, portalId, useShadowMode) {
        var m = new PortalMessage();
        m.messageType = PortalMessageType.ExitAttaching;
        m.sender = sender;
        m.portalId = portalId;
        m.useShadowMode = useShadowMode;
        return m;
    };
    PortalMessage.exitDetaching = function (sender, portalId) {
        var m = new PortalMessage();
        m.messageType = PortalMessageType.ExitDetaching;
        m.sender = sender;
        m.portalId = portalId;
        return m;
    };
    PortalMessage.entranceSlotContentUpdated = function (sender, portalId, content) {
        var m = new PortalMessage();
        m.messageType = PortalMessageType.EntranceSlotContentUpdated;
        m.sender = sender;
        m.portalId = portalId;
        m.content = content;
        return m;
    };
    return PortalMessage;
}());
var IgcPortalModule = /** @class */ /*@__PURE__*/ (function () {
    function IgcPortalModule() {
    }
    IgcPortalModule.register = function () {
        window.customElements.define("igc-portal-entrance", IgcPortalEntranceComponent);
        window.customElements.define("igc-portal-exit", IgcPortalExitComponent);
        window.customElements.define("igc-portal-item", IgcPortalItemComponent);
    };
    return IgcPortalModule;
}());
export { IgcPortalModule };
