var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
    function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
    var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
    var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
    var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
    var _, done = false;
    for (var i = decorators.length - 1; i >= 0; i--) {
        var context = {};
        for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
        for (var p in contextIn.access) context.access[p] = contextIn.access[p];
        context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
        var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
        if (kind === "accessor") {
            if (result === void 0) continue;
            if (result === null || typeof result !== "object") throw new TypeError("Object expected");
            if (_ = accept(result.get)) descriptor.get = _;
            if (_ = accept(result.set)) descriptor.set = _;
            if (_ = accept(result.init)) initializers.unshift(_);
        }
        else if (_ = accept(result)) {
            if (kind === "field") initializers.unshift(_);
            else descriptor[key] = _;
        }
    }
    if (target) Object.defineProperty(target, contextIn.name, descriptor);
    done = true;
};
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
    var useValue = arguments.length > 2;
    for (var i = 0; i < initializers.length; i++) {
        value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
    }
    return useValue ? value : void 0;
};
import * as plugins from '../plugins.js';
import * as appstate from '../appstate.js';
import * as interfaces from '../../dist_ts_interfaces/index.js';
import { appRouter } from '../router.js';
import './ob-auth-gate.js';
import { DeesElement, customElement, html, state, css, cssManager, } from '@design.estate/dees-element';
let ObAppShell = (() => {
    let _classDecorators = [customElement('ob-app-shell')];
    let _classDescriptor;
    let _classExtraInitializers = [];
    let _classThis;
    let _classSuper = DeesElement;
    let _loginState_decorators;
    let _loginState_initializers = [];
    let _loginState_extraInitializers = [];
    let _uiState_decorators;
    let _uiState_initializers = [];
    let _uiState_extraInitializers = [];
    let _systemState_decorators;
    let _systemState_initializers = [];
    let _systemState_extraInitializers = [];
    let _globalMessages_decorators;
    let _globalMessages_initializers = [];
    let _globalMessages_extraInitializers = [];
    var ObAppShell = class extends _classSuper {
        static { _classThis = this; }
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
            _loginState_decorators = [state()];
            _uiState_decorators = [state()];
            _systemState_decorators = [state()];
            _globalMessages_decorators = [state()];
            __esDecorate(this, null, _loginState_decorators, { kind: "accessor", name: "loginState", static: false, private: false, access: { has: obj => "loginState" in obj, get: obj => obj.loginState, set: (obj, value) => { obj.loginState = value; } }, metadata: _metadata }, _loginState_initializers, _loginState_extraInitializers);
            __esDecorate(this, null, _uiState_decorators, { kind: "accessor", name: "uiState", static: false, private: false, access: { has: obj => "uiState" in obj, get: obj => obj.uiState, set: (obj, value) => { obj.uiState = value; } }, metadata: _metadata }, _uiState_initializers, _uiState_extraInitializers);
            __esDecorate(this, null, _systemState_decorators, { kind: "accessor", name: "systemState", static: false, private: false, access: { has: obj => "systemState" in obj, get: obj => obj.systemState, set: (obj, value) => { obj.systemState = value; } }, metadata: _metadata }, _systemState_initializers, _systemState_extraInitializers);
            __esDecorate(this, null, _globalMessages_decorators, { kind: "accessor", name: "globalMessages", static: false, private: false, access: { has: obj => "globalMessages" in obj, get: obj => obj.globalMessages, set: (obj, value) => { obj.globalMessages = value; } }, metadata: _metadata }, _globalMessages_initializers, _globalMessages_extraInitializers);
            __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
            ObAppShell = _classThis = _classDescriptor.value;
            if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
        }
        #loginState_accessor_storage = __runInitializers(this, _loginState_initializers, { identity: null, phase: 'anonymous', generation: 0 });
        get loginState() { return this.#loginState_accessor_storage; }
        set loginState(value) { this.#loginState_accessor_storage = value; }
        #uiState_accessor_storage = (__runInitializers(this, _loginState_extraInitializers), __runInitializers(this, _uiState_initializers, {
            activeView: 'dashboard',
            activeSubview: null,
            autoRefresh: true,
            refreshInterval: 30000,
        }));
        get uiState() { return this.#uiState_accessor_storage; }
        set uiState(value) { this.#uiState_accessor_storage = value; }
        #systemState_accessor_storage = (__runInitializers(this, _uiState_extraInitializers), __runInitializers(this, _systemState_initializers, {
            status: null,
            resource: appstate.systemStatePart.getState().resource,
        }));
        get systemState() { return this.#systemState_accessor_storage; }
        set systemState(value) { this.#systemState_accessor_storage = value; }
        #globalMessages_accessor_storage = (__runInitializers(this, _systemState_extraInitializers), __runInitializers(this, _globalMessages_initializers, []));
        get globalMessages() { return this.#globalMessages_accessor_storage; }
        set globalMessages(value) { this.#globalMessages_accessor_storage = value; }
        viewTabs = (__runInitializers(this, _globalMessages_extraInitializers), [
            {
                slug: 'dashboard',
                name: 'Dashboard',
                iconName: 'lucide:layoutDashboard',
                element: (async () => (await import('./ob-view-dashboard.js')).ObViewDashboard)(),
            },
            {
                slug: 'apps',
                name: 'Apps',
                iconName: 'lucide:store',
                subViews: [
                    {
                        slug: 'app-store',
                        name: 'App Store',
                        iconName: 'lucide:store',
                        element: (async () => (await import('./ob-view-appstore.js')).ObViewAppStore)(),
                    },
                    {
                        slug: 'services',
                        name: 'Services',
                        iconName: 'lucide:boxes',
                        element: (async () => (await import('./ob-view-services.js')).ObViewServices)(),
                    },
                ],
            },
            {
                slug: 'network',
                name: 'Network',
                iconName: 'lucide:network',
                subViews: [
                    {
                        slug: 'proxy',
                        name: 'Proxy',
                        iconName: 'lucide:route',
                        element: (async () => (await import('./ob-view-network.js')).ObViewNetwork)(),
                    },
                    {
                        slug: 'domains',
                        name: 'Domains',
                        iconName: 'lucide:globe',
                        element: (async () => (await import('./ob-view-domains.js')).ObViewDomains)(),
                    },
                    {
                        slug: 'dns-records',
                        name: 'DNS Records',
                        iconName: 'lucide:listTree',
                        element: (async () => (await import('./ob-view-dns-records.js')).ObViewDnsRecords)(),
                    },
                ],
            },
            {
                slug: 'registry',
                name: 'Registry',
                iconName: 'lucide:package',
                subViews: [
                    {
                        slug: 'registries',
                        name: 'Registries',
                        iconName: 'lucide:package',
                        element: (async () => (await import('./ob-view-registries.js')).ObViewRegistries)(),
                    },
                    {
                        slug: 'tokens',
                        name: 'Tokens',
                        iconName: 'lucide:key',
                        element: (async () => (await import('./ob-view-tokens.js')).ObViewTokens)(),
                    },
                ],
            },
            {
                slug: 'settings',
                name: 'Settings',
                iconName: 'lucide:settings',
                element: (async () => (await import('./ob-view-settings.js')).ObViewSettings)(),
            },
        ]);
        resolvedViewTabs = [];
        initializedAppDashes = new WeakSet();
        suppressedUpdateVersion = '';
        upgradeFlowRunning = false;
        constructor() {
            super();
            document.title = 'Onebox';
            const loginSubscription = appstate.loginStatePart
                .select((stateArg) => stateArg)
                .subscribe((loginState) => {
                this.loginState = loginState;
                this.updateGlobalMessages();
                if (appstate.isAuthenticatedSession()) {
                    void this.initializeAuthenticatedDashboard(loginState.generation).catch((error) => {
                        console.error('Failed to initialize authenticated dashboard:', error);
                    });
                }
            });
            this.rxSubscriptions.push(loginSubscription);
            const systemSubscription = appstate.systemStatePart
                .select((stateArg) => stateArg)
                .subscribe((systemState) => {
                this.systemState = systemState;
                this.updateGlobalMessages();
            });
            this.rxSubscriptions.push(systemSubscription);
            const uiSubscription = appstate.uiStatePart
                .select((stateArg) => stateArg)
                .subscribe((uiState) => {
                this.uiState = uiState;
                this.syncAppdashView(uiState.activeView, uiState.activeSubview);
            });
            this.rxSubscriptions.push(uiSubscription);
        }
        async resolveViewTabs(tabs) {
            return Promise.all(tabs.map(async (tab) => {
                const resolvedTab = {
                    slug: tab.slug,
                    name: tab.name,
                    iconName: tab.iconName,
                };
                if (tab.element) {
                    resolvedTab.element = await tab.element;
                }
                if (tab.subViews) {
                    resolvedTab.subViews = await this.resolveViewTabs(tab.subViews);
                }
                return resolvedTab;
            }));
        }
        slugFor(view) {
            return view.slug ?? view.name.toLowerCase().replace(/\s+/g, '-');
        }
        findParent(view) {
            return this.resolvedViewTabs.find((viewTab) => viewTab.subViews?.includes(view));
        }
        findViewBySlug(viewSlug, subviewSlug) {
            const topLevelView = this.resolvedViewTabs.find((view) => this.slugFor(view) === viewSlug);
            if (!topLevelView)
                return undefined;
            if (subviewSlug && topLevelView.subViews) {
                return topLevelView.subViews.find((subview) => this.slugFor(subview) === subviewSlug) ?? topLevelView;
            }
            return topLevelView;
        }
        get currentViewTab() {
            if (this.resolvedViewTabs.length === 0)
                return undefined;
            return this.findViewBySlug(this.uiState.activeView, this.uiState.activeSubview) ?? this.resolvedViewTabs[0];
        }
        static styles = [
            cssManager.defaultStyles,
            css `
      :host {
        display: block;
        width: 100%;
        height: 100%;
      }
      .maincontainer {
        width: 100%;
        height: 100vh;
      }
      .dashboard {
        width: 100%;
        height: 100%;
      }
      .session-status {
        min-height: 100%;
        display: grid;
        place-items: center;
        color: ${cssManager.bdTheme('#52525b', '#a1a1aa')};
        background: ${cssManager.bdTheme('#fafafa', '#09090b')};
      }
      .session-card {
        padding: 24px;
        border-radius: 12px;
        background: ${cssManager.bdTheme('#ffffff', '#18181b')};
        box-shadow: 0 8px 30px rgb(0 0 0 / 10%);
      }
    `,
        ];
        render() {
            if (this.loginState.phase === 'verifying') {
                return html `
        <div class="maincontainer session-status">
          <div class="session-card">
            ${this.loginState.verificationError
                    ? html `
                  <p>${this.loginState.verificationError}</p>
                  <dees-button
                    .text=${'Retry verification'}
                    @click=${() => void appstate.verifyPersistedSession()}
                  ></dees-button>
                `
                    : 'Verifying your Onebox session…'}
          </div>
        </div>
      `;
            }
            if (this.loginState.phase === 'anonymous') {
                return html `
        <div class="maincontainer">
          <ob-auth-gate @authenticated=${this.handleAuthenticated}></ob-auth-gate>
        </div>
      `;
            }
            if (this.loginState.phase !== 'authenticated' || !appstate.isAuthenticatedSession()) {
                return html `
        <div class="maincontainer session-status">
          <div class="session-card">Signing out of Onebox…</div>
        </div>
      `;
            }
            return html `
      <div class="maincontainer">
        <div class="dashboard">
          <dees-simple-appdash
            name="Onebox"
            .viewTabs=${this.resolvedViewTabs}
            .selectedView=${this.currentViewTab}
            .globalMessages=${this.globalMessages}
          >
          </dees-simple-appdash>
        </div>
      </div>
    `;
        }
        async firstUpdated() {
            this.resolvedViewTabs = await this.resolveViewTabs(this.viewTabs);
            this.requestUpdate();
            await this.updateComplete;
            await appstate.verifyPersistedSession();
            const loginState = appstate.getRequiredState(appstate.loginStatePart);
            if (appstate.isAuthenticatedSession()) {
                await this.initializeAuthenticatedDashboard(loginState.generation);
            }
        }
        async initializeAuthenticatedDashboard(generationArg) {
            if (!this.isConnected || this.resolvedViewTabs.length === 0)
                return;
            const beforeRender = appstate.getRequiredState(appstate.loginStatePart);
            if (!appstate.isAuthenticatedSession() || beforeRender.generation !== generationArg)
                return;
            this.requestUpdate();
            await this.updateComplete;
            const currentSession = appstate.getRequiredState(appstate.loginStatePart);
            if (!appstate.isAuthenticatedSession() || currentSession.generation !== generationArg)
                return;
            const appDash = this.shadowRoot.querySelector('dees-simple-appdash');
            if (!appDash || this.initializedAppDashes.has(appDash))
                return;
            this.initializedAppDashes.add(appDash);
            appDash.addEventListener('view-select', (eventArg) => {
                const view = eventArg.detail.view;
                const parent = this.findParent(view);
                const currentState = appstate.getRequiredState(appstate.uiStatePart);
                if (parent) {
                    const parentSlug = this.slugFor(parent);
                    const subviewSlug = this.slugFor(view);
                    if (currentState.activeView === parentSlug && currentState.activeSubview === subviewSlug) {
                        return;
                    }
                    appRouter.navigateToView(parentSlug, subviewSlug);
                }
                else {
                    const slug = this.slugFor(view);
                    if (currentState.activeView === slug && !currentState.activeSubview)
                        return;
                    appRouter.navigateToView(slug);
                }
            });
            appDash.addEventListener('logout', () => {
                void appstate.logout();
            });
            const currentUiState = appstate.getRequiredState(appstate.uiStatePart);
            const initialView = this.findViewBySlug(currentUiState.activeView, currentUiState.activeSubview) || this.resolvedViewTabs[0];
            await appDash.loadView(initialView);
        }
        handleAuthenticated = async (eventArg) => {
            await appstate.acceptIdentity(eventArg.detail.identity);
        };
        updateGlobalMessages() {
            const updateStatus = this.systemState.status?.onebox.update;
            if (!appstate.isAuthenticatedSession() ||
                !updateStatus?.updateAvailable ||
                !updateStatus.latestVersion ||
                updateStatus.latestVersion === this.suppressedUpdateVersion) {
                this.globalMessages = [];
                return;
            }
            this.globalMessages = [
                {
                    id: `onebox-update-${updateStatus.latestVersion}`,
                    type: 'info',
                    icon: 'lucide:download',
                    message: `Onebox ${updateStatus.latestVersion} is available. Current version: ${updateStatus.currentVersion}.`,
                    dismissible: false,
                    actions: [
                        {
                            name: 'Update Now',
                            iconName: 'lucide:download',
                            action: () => this.startOneboxUpgradeFlow(),
                        },
                        {
                            name: 'Release Notes',
                            iconName: 'lucide:fileText',
                            action: () => this.openUpdateUrl(updateStatus.changelogUrl || updateStatus.releaseUrl),
                        },
                        {
                            name: 'Later',
                            iconName: 'lucide:clock',
                            action: () => {
                                this.suppressedUpdateVersion = updateStatus.latestVersion || '';
                                this.updateGlobalMessages();
                            },
                        },
                    ],
                },
            ];
        }
        async startOneboxUpgradeFlow() {
            if (this.upgradeFlowRunning) {
                return;
            }
            const updateStatus = this.systemState.status?.onebox.update;
            if (!appstate.isAuthenticatedSession() || !updateStatus?.latestVersion) {
                return;
            }
            this.upgradeFlowRunning = true;
            const updater = await plugins.deesCatalog.DeesUpdater.createAndShow({
                appName: 'Onebox',
                appIcon: 'lucide:box',
                currentVersion: updateStatus.currentVersion,
                updatedVersion: updateStatus.latestVersion,
                updateSource: updateStatus.releaseUrl ? 'Onebox release channel' : '',
                impactItems: [
                    'The Onebox service restarts while the new package build is installed.',
                    'The browser may briefly lose connection during the restart.',
                    'The UI reloads after the new version is verified.',
                ],
                moreInfoUrl: updateStatus.releaseUrl,
                changelogUrl: updateStatus.changelogUrl,
                successAction: 'reload',
                successDelayMs: 30000,
                successActionLabel: 'Reloading Onebox UI',
            });
            try {
                updater.setPhase('checking', {
                    percentage: 10,
                    indeterminate: true,
                    statusText: 'Requesting upgrade...',
                    line: 'Requesting Onebox upgrade',
                });
                const response = await appstate.runProtectedRequest('onebox.upgrade.start', { targetVersion: updateStatus.latestVersion }, async (identity) => await new plugins.domtools.plugins.typedrequest.TypedRequest('/typedrequest', 'startOneboxUpgrade').fire({ identity }), { mode: 'mutation', domain: 'onebox.upgrade' });
                if (!response)
                    return;
                if (!response.upgrade.accepted) {
                    updater.markUpdateError(response.upgrade.message);
                    return;
                }
                updater.setPhase('downloading', {
                    percentage: 35,
                    statusText: 'Upgrade accepted...',
                    line: response.upgrade.message,
                });
                if (response.upgrade.pid) {
                    updater.appendProgressLine(`Upgrade process PID: ${response.upgrade.pid}`);
                }
                if (response.upgrade.logPath) {
                    updater.appendProgressLine(`Upgrade log: ${response.upgrade.logPath}`);
                }
                updater.setPhase('installing', {
                    percentage: 45,
                    indeterminate: true,
                    statusText: 'Installer started...',
                    line: 'Installer started',
                });
                const verified = await this.waitForOneboxUpgrade(updater, response.upgrade.targetVersion);
                if (verified) {
                    await updater.markUpdateReady();
                }
                else {
                    updater.markUpdateWarning(`The upgrade command was accepted, but Onebox ${this.normalizeVersion(response.upgrade.targetVersion)} could not be verified before the timeout.`, { line: 'Timed out waiting for the version check' });
                }
            }
            catch (error) {
                updater.markUpdateError(this.getErrorMessage(error));
            }
            finally {
                this.upgradeFlowRunning = false;
            }
        }
        async waitForOneboxUpgrade(updaterArg, targetVersionArg) {
            const normalizedTargetVersion = this.normalizeVersion(targetVersionArg);
            const timeoutAt = Date.now() + 90000;
            let attempt = 0;
            updaterArg.setPhase('restarting', {
                percentage: 55,
                statusText: 'Waiting for Onebox to restart...',
                line: 'Waiting for Onebox to restart with the new version',
            });
            while (Date.now() < timeoutAt) {
                await this.delay(5000);
                attempt++;
                try {
                    const response = await appstate.runProtectedRequest('onebox.upgrade.verify', { targetVersion: normalizedTargetVersion }, async (identity) => await new plugins.domtools.plugins.typedrequest.TypedRequest('/typedrequest', 'getSystemStatus').fire({ identity }), { mode: 'latest' });
                    if (!response)
                        return false;
                    const onlineVersion = this.normalizeVersion(response.status.onebox.version);
                    updaterArg.setPhase('verifyingApp', {
                        percentage: Math.min(95, 65 + attempt * 5),
                        statusText: `Onebox API answered with ${onlineVersion}.`,
                        line: `Onebox API answered with ${onlineVersion}`,
                    });
                    if (onlineVersion === normalizedTargetVersion) {
                        updaterArg.updateProgress({
                            percentage: 100,
                            indeterminate: false,
                            statusText: `Onebox ${normalizedTargetVersion} is online.`,
                        });
                        return true;
                    }
                }
                catch {
                    updaterArg.setPhase('restarting', {
                        percentage: Math.min(95, 55 + attempt * 5),
                        indeterminate: true,
                        statusText: `Waiting for Onebox ${normalizedTargetVersion}...`,
                        line: 'Onebox API is restarting...',
                    });
                }
            }
            return false;
        }
        openUpdateUrl(urlArg) {
            window.open(urlArg, '_blank', 'noopener,noreferrer');
        }
        async delay(millisecondsArg) {
            const domtools = await this.domtoolsPromise;
            await domtools.convenience.smartdelay.delayFor(millisecondsArg);
        }
        getErrorMessage(errorArg) {
            return errorArg instanceof Error ? errorArg.message : String(errorArg);
        }
        normalizeVersion(versionArg) {
            const trimmedVersion = versionArg.trim();
            return trimmedVersion.startsWith('v') ? trimmedVersion : `v${trimmedVersion}`;
        }
        syncAppdashView(viewName, subviewName) {
            const appDash = this.shadowRoot?.querySelector('dees-simple-appdash');
            if (!appDash || this.resolvedViewTabs.length === 0)
                return;
            const targetTab = this.findViewBySlug(viewName, subviewName);
            if (!targetTab || appDash.selectedView === targetTab)
                return;
            appDash.loadView(targetTab);
        }
        static {
            __runInitializers(_classThis, _classExtraInitializers);
        }
    };
    return ObAppShell = _classThis;
})();
export { ObAppShell };
//# sourceMappingURL=data:application/json;base64, 