/*
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.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);
        }
        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);
            }
        }
    }
    replaceRootItem(t, continueActions) {
        for (let i = this.element.children.length - 1; i >= 0; i--) {
            this.element.children[i].remove();
        }
        let C = t;
        if (C.htmlTagName) {
            t = document.createElement(t.htmlTagName);
        }
        else {
            t = new C();
        }
        this._currentRoot = t;
        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);
        }
        let parent = 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);
                            }
                        }
                    }
                });
                this._observer.observe(parent, { attributes: true });
            }
            else {
                this._observer.observe(parent, { attributes: true });
            }
        }
        continueActions(false);
    }
    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;
    }
}
