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 __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
(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", "../../App", "../../core/BindableProperty", "./AtomControl", "./AtomTemplate"], factory);
    }
})(function (require, exports) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    var App_1 = require("../../App");
    var BindableProperty_1 = require("../../core/BindableProperty");
    var AtomControl_1 = require("./AtomControl");
    var AtomTemplate_1 = require("./AtomTemplate");
    function getTemplateParent(e) {
        var tp = e._templateParent;
        if (tp) {
            return tp;
        }
        var p = e._logicalParent || e.parentElement;
        if (p) {
            return getTemplateParent(p);
        }
    }
    exports.getTemplateParent = getTemplateParent;
    var AtomWindowFrameTemplate = /** @class */ (function (_super) {
        __extends(AtomWindowFrameTemplate, _super);
        function AtomWindowFrameTemplate() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        Object.defineProperty(AtomWindowFrameTemplate.prototype, "templateParent", {
            get: function () {
                return getTemplateParent(this.element);
            },
            enumerable: true,
            configurable: true
        });
        AtomWindowFrameTemplate.prototype.create = function () {
            // remember, if you do not wish to use dynamic themes
            // then use one time binding
            this.bind(this.element, "styleClass", [["templateParent", "controlStyle", "frame"]]);
            this.bind(this.element, "styleWidth", [["templateParent", "width"]], false, function (v) { return v || undefined; });
            this.bind(this.element, "styleHeight", [["templateParent", "height"]], false, function (v) { return v || undefined; });
            this.bind(this.element, "styleLeft", [["templateParent", "x"]], false, function (v) { return v >= 0 ? v + "px" : undefined; });
            this.bind(this.element, "styleTop", [["templateParent", "y"]], false, function (v) { return v >= 0 ? v + "px" : undefined; });
            this.bind(this.element, "styleMarginTop", [["templateParent", "x"]], false, function (v) { return v >= 0 ? "0" : undefined; });
            this.bind(this.element, "styleMarginLeft", [["templateParent", "x"]], false, function (v) { return v >= 0 ? "0" : undefined; });
            this.bind(this.element, "styleMarginRight", [["templateParent", "x"]], false, function (v) { return v >= 0 ? "0" : undefined; });
            this.bind(this.element, "styleMarginBottom", [["templateParent", "x"]], false, function (v) { return v >= 0 ? "0" : undefined; });
            // add title host
            var titlePresenter = document.createElement("div");
            this.bind(titlePresenter, "styleClass", [["templateParent", "controlStyle", "titlePresenter"]]);
            // titleHost.classList.add(style.titleHost.className);
            this.titlePresenter = titlePresenter;
            this.element.appendChild(titlePresenter);
            // add content presenter
            var cp = document.createElement("div");
            this.bind(cp, "styleClass", [["templateParent", "controlStyle", "content"]]);
            // cp.classList.add(style.content.className);
            this.contentPresenter = cp;
            this.element.appendChild(cp);
            // create command presenter
            var cdp = document.createElement("div");
            // cdp.classList.add(style.commandBar.className);
            this.bind(cdp, "styleClass", [["templateParent", "controlStyle", "commandBar"]]);
            this.commandPresenter = cdp;
            this.element.appendChild(cdp);
        };
        return AtomWindowFrameTemplate;
    }(AtomTemplate_1.AtomTemplate));
    exports.AtomWindowFrameTemplate = AtomWindowFrameTemplate;
    var AtomWindowTitleTemplate = /** @class */ (function (_super) {
        __extends(AtomWindowTitleTemplate, _super);
        function AtomWindowTitleTemplate() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        Object.defineProperty(AtomWindowTitleTemplate.prototype, "templateParent", {
            get: function () {
                return getTemplateParent(this.element);
            },
            enumerable: true,
            configurable: true
        });
        AtomWindowTitleTemplate.prototype.create = function () {
            var _this = this;
            this.bind(this.element, "styleClass", [["templateParent", "controlStyle", "titleHost"]]);
            // add title
            var title = document.createElement("span");
            this.bind(title, "styleClass", [["templateParent", "controlStyle", "title"]]);
            // title.classList.add(style.title.className);
            this.bind(title, "text", [["templateParent", "title"]], false);
            // add close button
            var closeButton = document.createElement("button");
            this.bind(closeButton, "styleClass", [["templateParent", "controlStyle", "closeButton"]]);
            // closeButton.textContent = "x";
            this.bindEvent(closeButton, "click", function (e) {
                var w = getTemplateParent(_this.element);
                w.close();
            });
            // append title host > title
            this.append(title);
            this.append(closeButton);
        };
        return AtomWindowTitleTemplate;
    }(AtomControl_1.AtomControl));
    var AtomWindow = /** @class */ (function (_super) {
        __extends(AtomWindow, _super);
        function AtomWindow() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.title = "";
            _this.width = "";
            _this.height = "";
            _this.x = -1;
            _this.y = -1;
            _this.titleTemplate = AtomWindowTitleTemplate;
            _this.frameTemplate = AtomWindowFrameTemplate;
            _this.isReady = false;
            return _this;
        }
        Object.defineProperty(AtomWindow.prototype, "templateParent", {
            get: function () {
                return getTemplateParent(this.element);
            },
            enumerable: true,
            configurable: true
        });
        AtomWindow.prototype.onPropertyChanged = function (name) {
            switch (name) {
                case "windowTemplate":
                case "commandTemplate":
                case "frameTemplate":
                    this.invalidate();
                    break;
            }
        };
        AtomWindow.prototype.close = function () {
            var vm = this.viewModel;
            if (vm.cancel) {
                this.app.runAsync(function () { return vm.cancel(); });
                return;
            }
            var message = "atom-window-cancel:" + this.id;
            var device = this.app.resolve(App_1.App);
            device.broadcast(message, "cancelled");
        };
        AtomWindow.prototype.onUpdateUI = function () {
            var _this = this;
            if (!(this.windowTemplate && this.frameTemplate)) {
                return;
            }
            if (this.isReady) {
                return;
            }
            this.bind(this.element, "title", [["viewModel", "title"]]);
            // let us create frame first...
            var frame = new (this.frameTemplate)(this.app);
            var fe = frame.element;
            // setup drag and drop for the frame...
            var titleContent = new (this.titleTemplate)(this.app);
            (titleContent.element)._templateParent = this;
            frame.titlePresenter.appendChild(titleContent.element);
            this.setupDragging(frame.titlePresenter);
            this.element.classList.add(this.controlStyle.frameHost.className);
            fe._logicalParent = this.element;
            fe._templateParent = this;
            if (!frame.contentPresenter) {
                throw new Error("ContentPresenter must be set inside frameTemplate before creating window");
            }
            var content = new (this.windowTemplate)(this.app);
            (content.element)._templateParent = this;
            frame.contentPresenter.appendChild(content.element);
            if (this.commandTemplate) {
                if (!frame.commandPresenter) {
                    throw new Error("CommandPresenter must be set inside frameTemplate" +
                        "before creating window if command template is present");
                }
                var command = new (this.commandTemplate)(this.app);
                (command.element)._templateParent = this;
                frame.commandPresenter.appendChild(command.element);
            }
            this.append(frame);
            // lets center frame...
            setTimeout(function () {
                _this.centerFrame(frame.element);
            }, 100);
            this.isReady = true;
        };
        AtomWindow.prototype.centerFrame = function (e) {
            var _this = this;
            /// window is destroyed probably..
            if (!this.element) {
                return;
            }
            var parent = this.element.parentElement;
            if (parent === window || parent === document.body) {
                return;
            }
            if (parent.offsetWidth <= 0 || parent.offsetHeight <= 0) {
                setTimeout(function () {
                    _this.centerFrame(e);
                }, 100);
                return;
            }
            if (e.offsetWidth <= 0 || e.offsetHeight <= 0) {
                setTimeout(function () {
                    _this.centerFrame(e);
                }, 100);
                return;
            }
            var x = (parent.offsetWidth - e.offsetWidth) / 2;
            var y = (parent.offsetHeight - e.offsetHeight) / 2;
            this.x = x;
            this.y = y;
            e.style.opacity = "1";
            this.element.style.removeProperty("opacity");
        };
        AtomWindow.prototype.setupDragging = function (tp) {
            var _this = this;
            this.bindEvent(tp, "mousedown", function (startEvent) {
                startEvent.preventDefault();
                var disposables = [];
                // const offset = AtomUI.screenOffset(tp);
                var offset = { x: tp.parentElement.offsetLeft, y: tp.parentElement.offsetTop };
                var rect = { x: startEvent.clientX, y: startEvent.clientY };
                var cursor = tp.style.cursor;
                tp.style.cursor = "move";
                disposables.push(_this.bindEvent(document.body, "mousemove", function (moveEvent) {
                    var clientX = moveEvent.clientX, clientY = moveEvent.clientY;
                    var dx = clientX - rect.x;
                    var dy = clientY - rect.y;
                    offset.x += dx;
                    offset.y += dy;
                    _this.x = offset.x;
                    _this.y = offset.y;
                    rect.x = clientX;
                    rect.y = clientY;
                }));
                disposables.push(_this.bindEvent(document.body, "mouseup", function (endEvent) {
                    tp.style.cursor = cursor;
                    for (var _i = 0, disposables_1 = disposables; _i < disposables_1.length; _i++) {
                        var iterator = disposables_1[_i];
                        iterator.dispose();
                    }
                }));
            });
        };
        __decorate([
            BindableProperty_1.BindableProperty,
            __metadata("design:type", String)
        ], AtomWindow.prototype, "title", void 0);
        __decorate([
            BindableProperty_1.BindableProperty,
            __metadata("design:type", String)
        ], AtomWindow.prototype, "width", void 0);
        __decorate([
            BindableProperty_1.BindableProperty,
            __metadata("design:type", String)
        ], AtomWindow.prototype, "height", void 0);
        __decorate([
            BindableProperty_1.BindableProperty,
            __metadata("design:type", Number)
        ], AtomWindow.prototype, "x", void 0);
        __decorate([
            BindableProperty_1.BindableProperty,
            __metadata("design:type", Number)
        ], AtomWindow.prototype, "y", void 0);
        __decorate([
            BindableProperty_1.BindableProperty,
            __metadata("design:type", Object)
        ], AtomWindow.prototype, "windowTemplate", void 0);
        __decorate([
            BindableProperty_1.BindableProperty,
            __metadata("design:type", Object)
        ], AtomWindow.prototype, "commandTemplate", void 0);
        __decorate([
            BindableProperty_1.BindableProperty,
            __metadata("design:type", Object)
        ], AtomWindow.prototype, "titleTemplate", void 0);
        __decorate([
            BindableProperty_1.BindableProperty,
            __metadata("design:type", Object)
        ], AtomWindow.prototype, "frameTemplate", void 0);
        return AtomWindow;
    }(AtomControl_1.AtomControl));
    exports.AtomWindow = AtomWindow;
});
//# sourceMappingURL=AtomWindow.js.map