/*
THIS INFRAGISTICS ULTIMATE SOFTWARE LICENSE  AGREEMENT ("AGREEMENT") LOCATED HERE:
https://www.infragistics.com/legal/license/igultimate-la
https://www.infragistics.com/legal/license/igultimate-eula
GOVERNS THE LICENSING, INSTALLATION AND USE OF INFRAGISTICS SOFTWARE. BY DOWNLOADING AND/OR INSTALLING AND USING INFRAGISTICS SOFTWARE:  you are indicating that you have read and understand this Agreement, and agree to be legally bound by it on behalf of the yourself and your company.
*/
import { IgEvent } from "./IgEvent";
import { shadowWrap } from "./igc-html-element";
export class IgcComponentRendererContainerComponent {
    constructor() {
        this._attrIgnoreList = ['class', 'style'];
        this.extraSlotNames = [];
        this.extraSlotNamesMap = new Set();
        this.shadowMode = false;
        this.childContentMode = false;
        this.portalMode = false;
        this.portalId = null;
        this.listeners = [];
        this._currentRoot = null;
    }
    static fromElement(ele) {
        if (ele.$$container) {
            return ele.$$container;
        }
        let c = new IgcComponentRendererContainerComponent();
        c.element = ele;
        if (ele.hasAttribute("shadow-dom-mode")) {
            let shadowRoot = shadowWrap(ele).attachShadow({ mode: "open" });
            c.element = shadowRoot;
            c.shadowMode = true;
        }
        if (ele.hasAttribute("child-content-mode")) {
            c.childContentMode = true;
            c.collectExtraSlots(ele);
        }
        if (ele.hasAttribute("portal-mode")) {
            c.portalMode = true;
            c.portalId = "portal-" + ele.getAttribute("data-ig-id");
        }
        ele.$$container = c;
        return c;
    }
    collectExtraSlots(ele) {
        for (var i = 0; i < ele.children.length; i++) {
            let child = ele.children[i];
            if (child.hasAttribute("slot")) {
                if (!this.extraSlotNamesMap.has(child.getAttribute("slot"))) {
                    this.extraSlotNames.push(child.getAttribute("slot"));
                    this.extraSlotNamesMap.add(child.getAttribute("slot"));
                }
            }
        }
    }
    ensureExtraSlots(ele) {
        let exist = new Set();
        for (var i = 0; i < ele.children.length; i++) {
            if (ele.children[i].tagName == "SLOT") {
                if (ele.hasAttribute("name")) {
                    exist.add(ele.getAttribute("name"));
                }
            }
        }
        for (var i = 0; i < this.extraSlotNames.length; i++) {
            if (!exist.has(this.extraSlotNames[i])) {
                let s = document.createElement("slot");
                s.setAttribute("name", this.extraSlotNames[i]);
                s.setAttribute("slot", this.extraSlotNames[i]);
                ele.append(s);
            }
        }
    }
    createObject(t, container, context) {
        if (typeof t == "string") {
            t = document.createElement(t);
        }
        else {
            let C = t;
            if (C.htmlTagName) {
                t = document.createElement(t.htmlTagName);
            }
            else {
                t = new C();
            }
        }
        return t;
    }
    replaceRootItem(t, deferAttach, continueActions) {
        for (let i = this.element.children.length - 1; i >= 0; i--) {
            this.element.children[i].remove();
        }
        if (typeof t == "string") {
            t = document.createElement(t);
        }
        else {
            let C = t;
            if (C.htmlTagName) {
                t = document.createElement(t.htmlTagName);
            }
            else {
                t = new C();
            }
        }
        this._currentRoot = t;
        if (!deferAttach) {
            this.element.appendChild(this._currentRoot);
        }
        this._currentRoot.width = "100%";
        this._currentRoot.height = "100%";
        if (this.childContentMode) {
            let slot = document.createElement("slot");
            this._currentRoot.appendChild(slot);
            this.ensureExtraSlots(this._currentRoot);
        }
        if (this.portalMode) {
            let portalExit = document.createElement("igc-portal-exit");
            portalExit.portalId = this.portalId;
            portalExit.useParentAsTarget = true;
            portalExit.moveOnceMode = true;
            this._currentRoot.appendChild(portalExit);
        }
        let parent = this.shadowMode ? this.element.host : this.element.parentElement;
        if (parent) {
            // sync attributes from the parent down to the root element.
            for (let i = 0; i < parent.attributes.length; i++) {
                let attr = parent.attributes.item(i);
                if (this._attrIgnoreList.includes(attr.name)) {
                    continue;
                }
                this._currentRoot.setAttribute(attr.name, attr.value);
                // this tells the component, if it supports it, that an attribute on it was synced from the parent.
                if (this._currentRoot.attributeSynced) {
                    this._currentRoot.attributeSynced(attr.name, attr.value);
                }
            }
            // setup an observer to watch for attribute changes so we can sync them with the root.
            if (!this._observer) {
                this._observer = new MutationObserver((mutationList, observer) => {
                    for (let i = 0; i < mutationList.length; i++) {
                        if (mutationList[i].type === 'attributes') {
                            let attrName = mutationList[i].attributeName;
                            if (this._attrIgnoreList.includes(attrName)) {
                                continue;
                            }
                            let attrValue = mutationList[i].target.getAttribute(attrName);
                            this._currentRoot.setAttribute(attrName, attrValue);
                            if (this._currentRoot.attributeSynced) {
                                this._currentRoot.attributeSynced(attrName, attrValue);
                            }
                        }
                        if (mutationList[i].type === 'childList') {
                            mutationList[i].removedNodes.forEach((value, key, parent) => {
                                if (value.hasAttribute("slot")) {
                                    const slotId = value.getAttribute("slot");
                                    for (let i = 0; i < this._currentRoot.children.length; i++) {
                                        let child = this._currentRoot.children[i];
                                        if (child.tagName === "SLOT" &&
                                            child.hasAttribute("name") &&
                                            child.hasAttribute("slot") &&
                                            child.getAttribute("name") === slotId &&
                                            child.getAttribute("slot") === slotId) {
                                            child.remove();
                                            i--;
                                        }
                                    }
                                    const slotIdx = this.extraSlotNames.indexOf(slotId);
                                    this.extraSlotNames.splice(slotIdx, 1);
                                    this.extraSlotNamesMap.delete(slotId);
                                }
                            });
                            mutationList[i].addedNodes.forEach((value, key, parent) => {
                                if (value.hasAttribute("slot")) {
                                    const slotId = value.getAttribute("slot");
                                    if (!this.extraSlotNamesMap.has(slotId)) {
                                        let s = document.createElement("slot");
                                        s.setAttribute("name", slotId);
                                        s.setAttribute("slot", slotId);
                                        this._currentRoot.append(s);
                                        this.extraSlotNames.push(slotId);
                                        this.extraSlotNamesMap.add(slotId);
                                    }
                                }
                            });
                        }
                    }
                });
                this._observer.observe(parent, { attributes: true, childList: this.childContentMode });
            }
            else {
                this._observer.observe(parent, { attributes: true, childList: this.childContentMode });
            }
        }
        continueActions(false);
        if (deferAttach) {
            this.element.appendChild(this._currentRoot);
        }
    }
    clearContainer(continueActions) {
        for (let i = this.element.children.length - 1; i >= 0; i--) {
            this.element.children[i].remove();
        }
        if (this._observer) {
            this._observer.disconnect();
        }
        continueActions(false);
    }
    getRootObject() {
        return this._currentRoot;
    }
    static isEvent(obj) {
        return obj instanceof IgEvent;
    }
}
