var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
(function (factory) {
    if (typeof module === "object" && typeof module.exports === "object") {
        var v = factory(require, exports);
        if (v !== undefined) module.exports = v;
    }
    else if (typeof define === "function" && define.amd) {
        define(["require", "exports", "../../core/AtomBinder", "../../core/AtomBridge", "../../core/AtomComponent", "../../core/FormattedString", "../../core/WebImage", "../../di/TypeKey", "../../services/NavigationService", "../styles/AtomStyle", "../styles/AtomStyleSheet"], factory);
    }
})(function (require, exports) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.AtomControl = void 0;
    const AtomBinder_1 = require("../../core/AtomBinder");
    const AtomBridge_1 = require("../../core/AtomBridge");
    const AtomComponent_1 = require("../../core/AtomComponent");
    const FormattedString_1 = require("../../core/FormattedString");
    const WebImage_1 = require("../../core/WebImage");
    const TypeKey_1 = require("../../di/TypeKey");
    const NavigationService_1 = require("../../services/NavigationService");
    const AtomStyle_1 = require("../styles/AtomStyle");
    const AtomStyleSheet_1 = require("../styles/AtomStyleSheet");
    if (typeof bridge !== "undefined" && bridge.platform) {
        throw new Error("AtomControl of Web should not be used with Xamarin Forms");
    }
    const bridgeInstance = AtomBridge_1.AtomBridge.instance;
    const defaultStyleSheets = {};
    /**
     * AtomControl class represents UI Component for a web browser.
     */
    class AtomControl extends AtomComponent_1.AtomComponent {
        constructor(app, e) {
            super(app, e || document.createElement("div"));
        }
        get controlStyle() {
            if (this.mControlStyle === undefined) {
                const key = TypeKey_1.TypeKey.get(this.defaultControlStyle || this.constructor);
                this.mControlStyle = defaultStyleSheets[key];
                if (this.mControlStyle) {
                    return this.mControlStyle;
                }
                if (this.defaultControlStyle) {
                    this.mControlStyle = defaultStyleSheets[key] ||
                        (defaultStyleSheets[key] = this.theme.createNamedStyle(this.defaultControlStyle, key));
                }
                this.mControlStyle = this.mControlStyle || null;
            }
            return this.mControlStyle;
        }
        set controlStyle(v) {
            if (v instanceof AtomStyle_1.AtomStyle) {
                this.mControlStyle = v;
            }
            else {
                const key = TypeKey_1.TypeKey.get(v);
                this.mControlStyle = defaultStyleSheets[key] ||
                    (defaultStyleSheets[key] = this.theme.createNamedStyle(v, key));
            }
            AtomBinder_1.AtomBinder.refreshValue(this, "controlStyle");
            this.invalidate();
        }
        /**
         * Represents associated AtomStyleSheet with this visual hierarchy. AtomStyleSheet is
         * inherited by default.
         */
        get theme() {
            return this.mTheme ||
                this.mCachedTheme ||
                (this.mCachedTheme = (this.parent ? this.parent.theme : this.app.resolve(AtomStyleSheet_1.AtomStyleSheet, false, null)));
        }
        set theme(v) {
            this.mTheme = v;
            bridgeInstance.refreshInherited(this, "theme");
        }
        /**
         * Gets Parent AtomControl of this control.
         */
        get parent() {
            const ep = this.element._logicalParent || this.element.parentElement;
            if (!ep) {
                return null;
            }
            return this.atomParent(ep);
        }
        onPropertyChanged(name) {
            super.onPropertyChanged(name);
            switch (name) {
                case "theme":
                    this.mCachedTheme = null;
                    AtomBinder_1.AtomBinder.refreshValue(this, "style");
                    break;
            }
        }
        atomParent(e) {
            if (!e) {
                return;
            }
            const ep = e;
            if (ep.atomControl) {
                return ep.atomControl;
            }
            return this.atomParent(ep._logicalParent || ep.parentElement);
        }
        append(element) {
            if (element instanceof AtomControl) {
                this.element.appendChild(element.element);
            }
            else {
                this.element.appendChild(element);
            }
            return this;
        }
        updateSize() {
            this.onUpdateSize();
            bridgeInstance.visitDescendents(this.element, (e, ac) => {
                if (ac) {
                    ac.updateSize();
                    return false;
                }
                return true;
            });
        }
        preCreate() {
            // if (!this.element) {
            //     this.element = document.createElement("div");
            // }
        }
        setElementValue(element, name, value) {
            if (value === undefined) {
                return;
            }
            if (/^style/.test(name)) {
                if (name.length === 5) {
                    element.setAttribute("style", value);
                    return;
                }
                name = name.substr(5);
                name = name.charAt(0).toLowerCase() + name.substr(1);
                // this is style class...
                if (name === "class") {
                    this.setElementClass(element, value);
                    return;
                }
                if (value instanceof WebImage_1.default) {
                    value = `url(${value})`;
                }
                element.style[name] = value;
                return;
            }
            if (/^event/.test(name)) {
                name = name.substr(5);
                name = name.charAt(0).toLowerCase() + name.substr(1);
                this.bindEvent(element, name, (...e) => __awaiter(this, void 0, void 0, function* () {
                    try {
                        const f = value;
                        const pr = f.apply(this, e);
                        if (pr) {
                            try {
                                yield pr;
                            }
                            catch (error) {
                                if (/canceled|cancelled/i.test(error)) {
                                    return;
                                }
                                const nav = this.app.resolve(NavigationService_1.NavigationService);
                                yield nav.alert(error, "Error");
                            }
                        }
                    }
                    catch (er1) {
                        // tslint:disable-next-line:no-console
                        console.error(er1);
                    }
                }));
                return;
            }
            switch (name) {
                case "text":
                    element.textContent = value;
                    break;
                case "formattedText":
                    if (value instanceof FormattedString_1.default) {
                        value.applyTo(this.app, element);
                    }
                    else {
                        element.textContent = (value || "").toString();
                    }
                    break;
                case "class":
                    this.setElementClass(element, value, true);
                    break;
                case "autofocus":
                    this.app.callLater(() => {
                        const ie = element;
                        if (ie) {
                            ie.focus();
                        }
                    });
                case "src":
                    if (value && /^http\:/i.test(value)) {
                        element.src = value.substr(5);
                    }
                    else {
                        element.src = value;
                    }
                    break;
                default:
                    element[name] = value;
            }
        }
        setElementClass(element, value, clear) {
            const s = value;
            if (s && typeof s === "object") {
                if (!s.className) {
                    if (clear) {
                        let sr = "";
                        for (const key in s) {
                            if (s.hasOwnProperty(key)) {
                                const sv = s[key];
                                if (sv) {
                                    sr += (sr ? (" " + key) : key);
                                }
                            }
                        }
                        element.className = sr;
                        return;
                    }
                    for (const key in s) {
                        if (s.hasOwnProperty(key)) {
                            const sv = s[key];
                            if (sv) {
                                if (!element.classList.contains(key)) {
                                    element.classList.add(key);
                                }
                            }
                            else {
                                if (element.classList.contains(key)) {
                                    element.classList.remove(key);
                                }
                            }
                        }
                    }
                    return;
                }
            }
            const sv1 = s ? (s.className || s.toString()) : "";
            element.className = sv1;
        }
        onUpdateSize() {
            // pending !!
        }
        removeAllChildren(e) {
            let child = e.firstElementChild;
            while (child) {
                const c = child;
                child = child.nextElementSibling;
                const ac = c;
                if (ac && ac.atomControl) {
                    ac.atomControl.dispose();
                }
                else {
                    // remove all children events
                    this.unbindEvent(child);
                    // remove all bindings
                    this.unbind(child);
                }
                c.remove();
            }
        }
    }
    exports.AtomControl = AtomControl;
    bridgeInstance.controlFactory = AtomControl;
});
//# sourceMappingURL=AtomControl.js.map