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);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
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", "../../App", "../../core/AtomBinder", "../../core/AtomList", "../../core/AtomLoader", "../../core/AtomOnce", "../../core/AtomUri", "../../core/Bind", "../../core/BindableProperty", "../../core/XNode", "../../di/Inject", "../../services/NavigationService", "../../view-model/AtomViewModel", "../../view-model/AtomWindowViewModel", "../../view-model/bindProperty", "../../view-model/bindUrlParameter", "../services/WindowService", "../styles/AtomTabbedPageStyle", "./AtomControl", "./AtomItemsControl", "./AtomPage"], factory);
    }
})(function (require, exports) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.AtomTabbedPage = void 0;
    const App_1 = require("../../App");
    const AtomBinder_1 = require("../../core/AtomBinder");
    const AtomList_1 = require("../../core/AtomList");
    const AtomLoader_1 = require("../../core/AtomLoader");
    const AtomOnce_1 = require("../../core/AtomOnce");
    const AtomUri_1 = require("../../core/AtomUri");
    const Bind_1 = require("../../core/Bind");
    const BindableProperty_1 = require("../../core/BindableProperty");
    const XNode_1 = require("../../core/XNode");
    const Inject_1 = require("../../di/Inject");
    const NavigationService_1 = require("../../services/NavigationService");
    const AtomViewModel_1 = require("../../view-model/AtomViewModel");
    const AtomWindowViewModel_1 = require("../../view-model/AtomWindowViewModel");
    const bindProperty_1 = require("../../view-model/bindProperty");
    const bindUrlParameter_1 = require("../../view-model/bindUrlParameter");
    const WindowService_1 = require("../services/WindowService");
    const AtomTabbedPageStyle_1 = require("../styles/AtomTabbedPageStyle");
    const AtomControl_1 = require("./AtomControl");
    const AtomItemsControl_1 = require("./AtomItemsControl");
    const AtomPage_1 = require("./AtomPage");
    const BindPage = Bind_1.default.forData();
    class AtomTabbedPage extends AtomControl_1.AtomControl {
        constructor(app, e) {
            super(app, e !== null && e !== void 0 ? e : document.createElement("section"));
        }
        get windowService() {
            return this.mWindowService || (this.mWindowService = this.resolve(WindowService_1.WindowService));
        }
        get selectedPage() {
            return this.mSelectedPage;
        }
        set selectedPage(value) {
            this.mSelectedPage = value;
            if (value && value.element) {
                const pe = value.element.parentElement;
                if (pe !== this.presenter) {
                    // const p = document.createElement("div");
                    // const s = p.style;
                    // p.className = "page-host";
                    // p.appendChild(value.element);
                    this.presenter.appendChild(value.element);
                    const ve = value;
                    value.bind(value.element, "styleDisplay", [["this", "selectedPage"]], false, (v) => v === ve ? "" : "none", this);
                }
            }
            this.invalidate();
            AtomBinder_1.AtomBinder.refreshValue(this, "selectedPage");
        }
        preCreate() {
            super.preCreate();
            this.defaultControlStyle = AtomTabbedPageStyle_1.AtomTabbedPageStyle;
            this.tabChannelName = "app";
            this.titleTemplate = null;
            this.mSelectedPage = null;
            this.runAfterInit(() => {
                this.setPrimitiveValue(this.element, "styleClass", this.controlStyle.name);
            });
            this.localViewModel = this.resolve(AtomTabViewModel, () => ({ owner: this }));
            this.render(XNode_1.default.create("section", { selectedPage: Bind_1.default.twoWays(() => this.localViewModel.selectedPage) },
                XNode_1.default.create(AtomTabbedPage.titleTemplate, null,
                    XNode_1.default.create("div", { styleClass: BindPage.oneWay((x) => ({
                            "tab-item": 1,
                            "selected-tab-item": x.data === this.localViewModel.selectedPage
                        })) },
                        XNode_1.default.create("div", { eventClick: BindPage.event((x) => this.localViewModel.selectedPage = x.data), text: BindPage.oneWay((x) => x.data.title) }),
                        XNode_1.default.create("img", { class: "close-button", eventClick: BindPage.event((x) => this.localViewModel.closePage(x.data)) }))),
                XNode_1.default.create(AtomItemsControl_1.AtomItemsControl, { class: "tabs", allowMultipleSelection: false, allowSelectFirst: true, items: Bind_1.default.oneWay(() => this.localViewModel.pages), selectedItem: Bind_1.default.twoWays(() => this.localViewModel.selectedPage), itemTemplate: Bind_1.default.oneWay(() => this.titleTemplate) }),
                XNode_1.default.create("div", { class: "presenter page-host", presenter: Bind_1.default.presenter("presenter") })));
            this.registerDisposable(this.windowService.registerHostForWindow((e) => this.getParentHost(e)));
            this.windowService.currentTarget = this.presenter;
        }
        getParentHost(e) {
            const pe = e._logicalParent || e.parentElement;
            if (pe === this.presenter) {
                return e.parentElement;
            }
            if (!pe) {
                return null;
            }
            return this.getParentHost(pe);
        }
    }
    exports.AtomTabbedPage = AtomTabbedPage;
    AtomTabbedPage.titleTemplate = XNode_1.default.prepare("titleTemplate", true, true);
    let AtomTabViewModel = class AtomTabViewModel extends AtomViewModel_1.AtomViewModel {
        constructor(app, owner) {
            super(app);
            this.owner = owner;
            this.pageUpdater = new AtomOnce_1.AtomOnce();
            this.pages = new AtomList_1.AtomList();
            bindProperty_1.default(this, this, "selectedUrl", this, [["selectedPage"]], {
                fromSource: (v) => {
                    return v.tag;
                },
                fromTarget: (v) => {
                    if (!this.pages) {
                        return null;
                    }
                    return this.pages.find((p) => p.tag === v);
                }
            });
            bindUrlParameter_1.default(this, "selectedUrl", "url");
        }
        init() {
            return __awaiter(this, void 0, void 0, function* () {
                const ch = this.owner.tabChannelName;
                this.storageKey = `${this.app.contextId}_${ch}`;
                const d = this.navigationService.registerNavigationHook((uri, { target }) => {
                    if (target === this.owner.tabChannelName ||
                        (uri.protocol === "tab:" && uri.host === this.owner.tabChannelName)) {
                        return this.loadPageForReturn(uri);
                    }
                });
                this.registerDisposable(d);
                const urls = sessionStorage.getItem(this.storageKey) || "null";
                const urlState = JSON.parse(urls) || {
                    name,
                    urls: [],
                    selectedUrl: null
                };
                for (const iterator of urlState.urls) {
                    const page = yield this.loadPage(new AtomUri_1.AtomUri(iterator), true);
                    if (page.tag === urlState.selectedUrl) {
                        this.pageUpdater.run(() => {
                            this.selectedPage = page;
                        });
                    }
                }
                if (!this.selectedPage) {
                    this.selectedPage = this.pages[0];
                }
            });
        }
        watchSelectedPage() {
            this.saveState(this.selectedPage);
        }
        closePage(page) {
            this.app.runAsync(() => this.navigationService.remove(page));
        }
        saveState(a) {
            const state = {
                urls: this.pages.map((p) => p.tag),
                selectedUrl: this.selectedUrl,
            };
            sessionStorage.setItem(this.storageKey, JSON.stringify(state));
        }
        loadPageForReturn(url) {
            return __awaiter(this, void 0, void 0, function* () {
                const p = yield this.loadPage(url, false);
                try {
                    return yield p.returnPromise;
                }
                catch (ex) {
                    // this will prevent warning in chrome for unhandled exception
                    if ((ex.message ? ex.message : ex) === "cancelled") {
                        // tslint:disable-next-line: no-console
                        console.warn(ex);
                        return;
                    }
                    throw ex;
                }
            });
        }
        loadPage(url, doNotSetSelected) {
            return __awaiter(this, void 0, void 0, function* () {
                const uriString = url.toString();
                const existing = this.pages.find((x) => x.tag === uriString);
                if (existing) {
                    if (!doNotSetSelected) {
                        if (this.selectedPage !== existing) {
                            this.selectedPage = existing;
                        }
                    }
                    return existing;
                }
                // const popupType = await UMD.resolveViewClassAsync(url.path);
                // const page: AtomPage = (new (popupType)(this.app)) as AtomPage;
                const { view: page, disposables } = yield AtomLoader_1.AtomLoader.loadView(url, this.app, true, () => new AtomWindowViewModel_1.AtomWindowViewModel(this.app));
                page.title = "Title";
                page.tag = uriString;
                if (url.query && url.query.title) {
                    page.title = url.query.title.toString();
                }
                page.bind(page.element, "title", [["viewModel", "title"]]);
                page.bind(page.element, "styleDisplay", [["this", "selectedPage"]], false, (v) => v === page ? "" : "none", this);
                this.pages.add(page);
                if (!doNotSetSelected) {
                    this.selectedPage = page;
                }
                const e = page.element;
                const ws = this.navigationService;
                ws.currentTarget = e;
                disposables.add(() => {
                    const index = this.pages.indexOf(page);
                    if (this.pages.length <= 1 && index <= 0) {
                        return;
                    }
                    this.pages.remove(page);
                    e.remove();
                    ws.currentTarget = null;
                    if (this.selectedPage === page) {
                        this.selectedPage = this.pages[index - 1];
                    }
                });
                this.saveState();
                return page;
            });
        }
    };
    __decorate([
        BindableProperty_1.BindableProperty,
        __metadata("design:type", AtomList_1.AtomList)
    ], AtomTabViewModel.prototype, "pages", void 0);
    __decorate([
        BindableProperty_1.BindableProperty,
        __metadata("design:type", AtomPage_1.AtomPage)
    ], AtomTabViewModel.prototype, "selectedPage", void 0);
    __decorate([
        BindableProperty_1.BindableProperty,
        __metadata("design:type", String)
    ], AtomTabViewModel.prototype, "selectedUrl", void 0);
    __decorate([
        BindableProperty_1.BindableProperty,
        __metadata("design:type", Object)
    ], AtomTabViewModel.prototype, "tabState", void 0);
    __decorate([
        Inject_1.Inject,
        __metadata("design:type", NavigationService_1.NavigationService)
    ], AtomTabViewModel.prototype, "navigationService", void 0);
    __decorate([
        AtomViewModel_1.Watch,
        __metadata("design:type", Function),
        __metadata("design:paramtypes", []),
        __metadata("design:returntype", void 0)
    ], AtomTabViewModel.prototype, "watchSelectedPage", null);
    AtomTabViewModel = __decorate([
        __param(0, Inject_1.Inject),
        __metadata("design:paramtypes", [App_1.App, AtomTabbedPage])
    ], AtomTabViewModel);
});
//# sourceMappingURL=AtomTabbedPage.js.map