var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
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());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
(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/types", "../../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;
    var AtomBinder_1 = require("../../core/AtomBinder");
    var AtomBridge_1 = require("../../core/AtomBridge");
    var AtomComponent_1 = require("../../core/AtomComponent");
    var FormattedString_1 = require("../../core/FormattedString");
    var types_1 = require("../../core/types");
    var WebImage_1 = require("../../core/WebImage");
    var TypeKey_1 = require("../../di/TypeKey");
    var NavigationService_1 = require("../../services/NavigationService");
    var AtomStyle_1 = require("../styles/AtomStyle");
    var AtomStyleSheet_1 = require("../styles/AtomStyleSheet");
    // export { default as WebApp } from "../WebApp";
    // if (!AtomBridge.platform) {
    //     AtomBridge.platform = "web";
    //     AtomBridge.instance = new AtomElementBridge();
    // } else {
    //     console.log(`Platform is ${AtomBridge.platform}`);
    // }
    var bridge = AtomBridge_1.AtomBridge.instance;
    var defaultStyleSheets = {};
    /**
     * AtomControl class represents UI Component for a web browser.
     */
    var AtomControl = /** @class */ (function (_super) {
        __extends(AtomControl, _super);
        function AtomControl(app, e) {
            return _super.call(this, app, e || document.createElement("div")) || this;
        }
        Object.defineProperty(AtomControl.prototype, "controlStyle", {
            get: function () {
                if (this.mControlStyle === undefined) {
                    var 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: function (v) {
                if (v instanceof AtomStyle_1.AtomStyle) {
                    this.mControlStyle = v;
                }
                else {
                    var 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();
            },
            enumerable: false,
            configurable: true
        });
        Object.defineProperty(AtomControl.prototype, "theme", {
            /**
             * Represents associated AtomStyleSheet with this visual hierarchy. AtomStyleSheet is
             * inherited by default.
             */
            get: function () {
                return this.mTheme ||
                    this.mCachedTheme ||
                    (this.mCachedTheme = (this.parent ? this.parent.theme : this.app.resolve(AtomStyleSheet_1.AtomStyleSheet, false, null)));
            },
            set: function (v) {
                this.mTheme = v;
                bridge.refreshInherited(this, "theme");
            },
            enumerable: false,
            configurable: true
        });
        Object.defineProperty(AtomControl.prototype, "parent", {
            /**
             * Gets Parent AtomControl of this control.
             */
            get: function () {
                var ep = this.element._logicalParent || this.element.parentElement;
                if (!ep) {
                    return null;
                }
                return this.atomParent(ep);
            },
            enumerable: false,
            configurable: true
        });
        AtomControl.prototype.onPropertyChanged = function (name) {
            _super.prototype.onPropertyChanged.call(this, name);
            switch (name) {
                case "theme":
                    this.mCachedTheme = null;
                    AtomBinder_1.AtomBinder.refreshValue(this, "style");
                    break;
            }
        };
        AtomControl.prototype.atomParent = function (e) {
            if (!e) {
                return;
            }
            var ep = e;
            if (ep.atomControl) {
                return ep.atomControl;
            }
            return this.atomParent(ep._logicalParent || ep.parentElement);
        };
        AtomControl.prototype.append = function (element) {
            if (element instanceof AtomControl) {
                this.element.appendChild(element.element);
            }
            else {
                this.element.appendChild(element);
            }
            return this;
        };
        AtomControl.prototype.updateSize = function () {
            this.onUpdateSize();
            bridge.visitDescendents(this.element, function (e, ac) {
                if (ac) {
                    ac.updateSize();
                    return false;
                }
                return true;
            });
        };
        AtomControl.prototype.preCreate = function () {
            // if (!this.element) {
            //     this.element = document.createElement("div");
            // }
        };
        AtomControl.prototype.setElementValue = function (element, name, value) {
            var _this = this;
            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);
                // element.style[name] = value;
                this.bindEvent(element, name, function () {
                    var e = [];
                    for (var _i = 0; _i < arguments.length; _i++) {
                        e[_i] = arguments[_i];
                    }
                    return __awaiter(_this, void 0, void 0, function () {
                        var pendingPromises, last, f, pr, error_1, nav, er1_1;
                        return __generator(this, function (_a) {
                            switch (_a.label) {
                                case 0:
                                    _a.trys.push([0, 7, , 8]);
                                    pendingPromises = element.pendingPromises;
                                    if (pendingPromises) {
                                        last = pendingPromises[name];
                                        if (last) {
                                            if (types_1.UMD.debug) {
                                                // tslint:disable-next-line:no-console
                                                console.warn("Previous promise exists for event " + name);
                                            }
                                            return [2 /*return*/];
                                        }
                                    }
                                    f = value;
                                    pr = f.apply(this, e);
                                    if (!pr) return [3 /*break*/, 6];
                                    if (!pendingPromises) {
                                        element.pendingPromises = pendingPromises = {};
                                    }
                                    pendingPromises[name] = pr;
                                    _a.label = 1;
                                case 1:
                                    _a.trys.push([1, 3, 5, 6]);
                                    return [4 /*yield*/, pr];
                                case 2:
                                    _a.sent();
                                    return [3 /*break*/, 6];
                                case 3:
                                    error_1 = _a.sent();
                                    if (/canceled|cancelled/i.test(error_1)) {
                                        return [2 /*return*/];
                                    }
                                    nav = this.app.resolve(NavigationService_1.NavigationService);
                                    return [4 /*yield*/, nav.alert(error_1, "Error")];
                                case 4:
                                    _a.sent();
                                    return [3 /*break*/, 6];
                                case 5:
                                    delete pendingPromises[name];
                                    return [7 /*endfinally*/];
                                case 6: return [3 /*break*/, 8];
                                case 7:
                                    er1_1 = _a.sent();
                                    // tslint:disable-next-line:no-console
                                    console.error(er1_1);
                                    return [3 /*break*/, 8];
                                case 8: return [2 /*return*/];
                            }
                        });
                    });
                });
                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(function () {
                        var 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;
            }
        };
        AtomControl.prototype.setElementClass = function (element, value, clear) {
            var s = value;
            if (s && typeof s === "object") {
                if (!s.className) {
                    if (clear) {
                        var sr = "";
                        for (var key in s) {
                            if (s.hasOwnProperty(key)) {
                                var sv = s[key];
                                if (sv) {
                                    sr += (sr ? (" " + key) : key);
                                }
                            }
                        }
                        element.className = sr;
                        return;
                    }
                    for (var key in s) {
                        if (s.hasOwnProperty(key)) {
                            var 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;
                }
            }
            var sv1 = s ? (s.className || s.toString()) : "";
            element.className = sv1;
        };
        AtomControl.prototype.onUpdateSize = function () {
            // pending !!
        };
        AtomControl.prototype.removeAllChildren = function (e) {
            var child = e.firstElementChild;
            while (child) {
                var c = child;
                child = child.nextElementSibling;
                var 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();
            }
        };
        return AtomControl;
    }(AtomComponent_1.AtomComponent));
    exports.AtomControl = AtomControl;
    bridge.controlFactory = AtomControl;
});
//# sourceMappingURL=AtomControl.js.map