import * as i0 from '@angular/core';
import { NgZone, Injectable, NgModule, Inject, inject, Optional, ChangeDetectionStrategy, Component } from '@angular/core';
import { setAngularJSGlobal, downgradeComponent, downgradeInjectable } from '@angular/upgrade/static';
import * as i1 from '@c8y/ngx-components';
import { DatePipe, ViewContext, EmptyComponent, AppStateService, RouterService, ActionService, PluginsResolveService, TenantUiService, RouterModule, hookNavigator, hookTab, hookActionBar, hookAction, hookBreadcrumb, hookDocs, BootstrapComponent, UserTotpRevokeComponent, DataGridComponent, LoadingComponent, RangeDisplayComponent, HelpComponent, HighlightComponent, EmptyStateComponent, PasswordInputComponent, HOOK_PATTERN_MESSAGES, HeaderService, AlertService, UserMenuService, DocsService, PasswordService, CachedLocaleDictionaryService, GlobalConfigService, ModalService, ChangeCurrentUserPasswordService, GainsightService, FilesService, ServiceRegistry, AssetLinkPipe, PropertyValueTransformService, FeatureCacheService, DateFormatService, NavigatorNodeRoot, getActivatedRoute, DynamicDatapointsResolver, DynamicManagedObjectResolver, C8yTranslateModule, hookComponent } from '@c8y/ngx-components';
import { UpgradedServicesModule } from '@c8y/ngx-components/upgrade/upgraded-services';
import * as angular from 'angular';
import { gettext } from '@c8y/ngx-components/gettext';
import { map, unary, find, forEach, startsWith, isArray, assign, every, pick, property, some, get } from 'lodash-es';
import { ReplaySubject, BehaviorSubject, merge, of, combineLatest, Observable, from, fromEventPattern, Subject, defer, debounceTime as debounceTime$1 } from 'rxjs';
import { take, delay, filter, map as map$1, debounceTime, switchMap, startWith, merge as merge$1, shareReplay } from 'rxjs/operators';
import { ResolveEnd, ActivationEnd, Router } from '@angular/router';
import { BasicAuth, FetchClient, QueriesUtil } from '@c8y/client';
import { AppLogsAutoRefreshComponent } from '@c8y/ngx-components/app-logs';
import { WidgetPreviewWrapperComponent, WidgetConfigService, ContextDashboardService } from '@c8y/ngx-components/context-dashboard';
import { DatapointSelectionListComponent, DatapointSelectorService } from '@c8y/ngx-components/datapoint-selector';
import { GlobalContextWidgetWrapperComponent, WidgetConfigMigrationService } from '@c8y/ngx-components/global-context';
import { PlatformConfigurationFormComponent } from '@c8y/ngx-components/platform-configuration';
import { RolesAssetTreeComponent } from '@c8y/ngx-components/user-roles';
import { PaginationComponent } from 'ngx-bootstrap/pagination';
import { ApiService } from '@c8y/ngx-components/api';
import { DeviceGridService } from '@c8y/ngx-components/device-grid';
import { DeviceTypeDetailEditedService } from '@c8y/ngx-components/device-protocols';
import * as i1$1 from '@ngx-translate/core';
import { TranslateService } from '@ngx-translate/core';
import { CommonModule } from '@angular/common';
import { AssetSelectorModule } from '@c8y/ngx-components/assets-navigator';

class AbsoluteDateService {
    constructor(datePipe) {
        this.datePipe = datePipe;
    }
    getFilter() {
        return (value, format = 'medium', timezone, locale) => this.datePipe.transform(value, format, timezone, locale);
    }
}
function absoluteDateServiceFactory(datePipe) {
    return new AbsoluteDateService(datePipe).getFilter();
}
const absoluteDateServiceProvider = {
    provide: AbsoluteDateService,
    useFactory: absoluteDateServiceFactory,
    deps: [DatePipe]
};

var ViewContextLegacyParameter;
(function (ViewContextLegacyParameter) {
    ViewContextLegacyParameter["Device"] = "deviceId";
    ViewContextLegacyParameter["Group"] = "groupId";
    ViewContextLegacyParameter["User"] = "userId";
    ViewContextLegacyParameter["Application"] = "applicationId";
    ViewContextLegacyParameter["Microservice"] = "applicationId";
    ViewContextLegacyParameter["SubscribedApplications"] = "applicationId";
    ViewContextLegacyParameter["Tenant"] = "tenantId";
    ViewContextLegacyParameter["Service"] = "deviceId";
    ViewContextLegacyParameter["Simulators"] = "deviceId"; // required to hook the Alarms tab to a Simulator view
})(ViewContextLegacyParameter || (ViewContextLegacyParameter = {}));
function c8yViewsProvider($routeProvider, c8yTabsProvider, c8yPathUtils) {
    'ngInject';
    const viewMap = {};
    const contextViews = new ReplaySubject();
    return {
        when,
        $get() {
            return {
                contextViews,
                when(path, cfg) {
                    return when(path, cfg, true);
                },
                getByPath,
                prefixWithSlash
            };
        }
    };
    /**
     * @ngdoc function
     * @name when
     * @methodOf c8y.ui.provider:c8yViewsProvider
     *
     * @description
     * Defines a view for given route.
     * If multiple views are defined for a single route then there will be a separate tab for each view available when user visits that route.
     *
     * @param path Target route.
     * @param cfg View configuration object with the following properties:
     *
     * - **name** - `string` - View's name (in case of multiple views at single route this will be displayed as tab's title).
     * - **priority** - `integer` - View's priority (in case of multiple views at single route this will determine the position of view's tab in the tabs stack).
     * - **icon** - `string` - Font Awesome icon name for the view (displayed on the tab's header).
     * - **showIf** - `function` - Function returning boolean value indicating whether to show a tab for the view or not.
     * - **templateUrl** - `string` - Path to the template to use for displaying the view.
     *
     * You can also provide other view options - the same as available for standard {@link https://docs.angularjs.org/api/ngRoute/provider/$routeProvider $routeProvider} in AngularJS.
     *
     * ```html
     * The following example demonstrates how to add a new view to device details route
     * (which will be displayed as a tab if other views are assigned to the same route):
     * <pre>
     *   c8yViewsProvider.when('/device/:deviceId', {
     *     name: 'Tracking',
     *     templateUrl: ':::PLUGIN_PATH:::/views/index.html',
     *     icon: 'crosshairs',
     *     showIf: ['$routeParams', 'c8yDevices', function ($routeParams, c8yDevices) {
     *       var deviceId = $routeParams.deviceId;
     *       return c8yDevices.detailCached(deviceId).then(function (res) {
     *         var device = res.data;
     *         return device && (device.c8y_MotionTracking || device.c8y_Geofence);
     *       });
     *     }]
     *   });
     * </pre>
     * ```
     */
    function when(path, cfg, runPhase) {
        const newPath = prefixWithSlash(path);
        cfg.resolve = cfg.resolve || {};
        // eslint-disable-next-line no-underscore-dangle
        cfg.resolve.__c8y_locales = [
            'c8yLocales',
            c8yLocales => {
                return c8yLocales.initDone;
            }
        ];
        let currentCfg = viewMap[newPath];
        const originalPath = newPath;
        if (!cfg.name) {
            // console.warn('View name not defined');
        }
        if (!currentCfg) {
            viewMap[newPath] = [];
            currentCfg = viewMap[newPath];
        }
        const upgradedContext = Object.keys(ViewContext)
            .map(key => ({
            key,
            isUpgrade: prefixWithSlash(ViewContext[key].replace('id', ViewContextLegacyParameter[key])) === path
        }))
            .find(({ isUpgrade }) => isUpgrade);
        if (upgradedContext) {
            currentCfg.push(cfg);
            cfg.path = newPath;
            const p = c8yPathUtils.appendSegment(originalPath.replace(path, ''), cfg.name);
            contextViews.next({
                ...cfg,
                path: cfg.name ? p.substring(1) : '',
                contextKey: upgradedContext.key,
                runPhase
            });
            cfg.showIf = undefined;
            if (cfg.name) {
                cfg.path = c8yPathUtils.appendSegment(originalPath, cfg.name);
            }
        }
        else {
            if (currentCfg.length === 1) {
                const [existingConfig] = currentCfg;
                existingConfig.path = c8yPathUtils.appendSegment(originalPath, existingConfig.name);
                existingConfig.tab = createTab(originalPath, existingConfig);
                $routeProvider.when(existingConfig.path, existingConfig);
            }
            currentCfg.push(cfg);
            cfg.path = newPath;
            if (currentCfg.length > 1) {
                cfg.path = c8yPathUtils.appendSegment(originalPath, cfg.name);
                createTab(originalPath, cfg);
                $routeProvider.when(prefixWithSlash(originalPath), {
                    resolveRedirectTo($route, $q, c8yUiUtil, c8yTabs, gettextCatalog) {
                        'ngInject';
                        const sortedCurrentCfg = c8yTabsProvider.sortTabsViews(currentCfg, gettextCatalog);
                        const params = $route.current.pathParams;
                        return $q
                            .all(map(sortedCurrentCfg, unary(c8yUiUtil.configureVisibility)))
                            .then(views => {
                            const first = find(views, 'show');
                            let url = first.path;
                            forEach(params, (val, key) => {
                                url = url.replace(`:${key}`, val);
                            });
                            c8yTabs.redirectedViewPath = url;
                            return url;
                        });
                    }
                });
            }
        }
        return $routeProvider.when(prefixWithSlash(cfg.path), cfg);
    }
    function getByPath(path) {
        return viewMap[prefixWithSlash(path)];
    }
    function createTab(path, cfg) {
        c8yTabsProvider.addTab(path, cfg);
    }
    function prefixWithSlash(path) {
        const prefix = startsWith(path, '/') ? '' : '/';
        return prefix + path;
    }
}

class BridgeService {
    constructor(injector, appState, router, ngZone, routerService, actionService) {
        this.injector = injector;
        this.appState = appState;
        this.router = router;
        this.ngZone = ngZone;
        this.routerService = routerService;
        this.actionService = actionService;
        this.$liveTabs = new BehaviorSubject([]);
        this.initialNavigationDone = false;
        this.fixE2eIssues();
        this.$ng1RouteChangeSuccess = this.fromNg1Event(this.injector.get('$rootScope'), '$routeChangeSuccess');
        this.$ng1RouteChangeStart = this.fromNg1Event(this.injector.get('$rootScope'), '$routeChangeStart');
        this.$ng1RouteUpdate = this.fromNg1Event(this.injector.get('$rootScope'), '$routeUpdate');
        this.hookLanguage();
        this.hookTab();
        this.hookNavigator();
        this.hookUserMenu();
        this.hookViewProvider();
        this.hookRoute();
        this.routerService.readyForInitialNavigation$.pipe(take(1), delay(1)).subscribe(() => {
            this.initialNavigationDone = true;
            this.router.initialNavigation();
        });
        this.ng1Routes();
    }
    /**
     * Ensure that angularjs routes are not using any
     * secondary router outlets
     */
    hookRoute() {
        this.router.events
            .pipe(filter(event => event instanceof ResolveEnd), map$1((event) => event.state.root.firstChild), filter(route => route && route.routeConfig && route.routeConfig.path === '**'))
            .subscribe((event) => {
            if (event.root.children.length > 1) {
                window.location.hash = event.root.children[0].url.toString();
            }
        });
    }
    hookViewProvider() {
        const c8yViews = this.injector.get('c8yViews');
        // fix to trigger an angularjs route change success
        // event on context route match to make legacy
        // view-providers resolve.
        c8yViews.when('/device/:id', {
            template: ''
        });
        c8yViews.when('/group/:id', {
            template: ''
        });
        c8yViews.contextViews.subscribe(cfg => this.addRoute(cfg));
    }
    addRoute(cfg) {
        this.routerService.addRoute({
            label: cfg.label || cfg.name,
            path: cfg.path,
            icon: cfg.icon,
            context: ViewContext[cfg.contextKey],
            priority: cfg.priority,
            component: EmptyComponent,
            data: {
                showIf: cfg.showIf
                    ? ngxRoute => {
                        const params = {
                            ...ngxRoute.params,
                            [ViewContextLegacyParameter[cfg.contextKey]]: ngxRoute.params.id
                        };
                        const showIfResult = this.injector.invoke(cfg.showIf, undefined, {
                            $routeParams: params
                        });
                        // make sure showIf result is a promise with boolean result:
                        return this.injector.get('$q').when(showIfResult).then(Boolean);
                    }
                    : undefined
            },
            ...(cfg.featureId && { featureId: cfg.featureId })
        });
        if (cfg.runPhase) {
            this.routerService.refresh();
        }
    }
    ng1Routes() {
        const template = '';
        const fallbackRoutes = [];
        for (const context in ViewContext) {
            if (ViewContext[context] !== ViewContext.Alarms) {
                const path = ViewContext[context].match(/(\w+)\//)[1];
                const regexp = new RegExp(`^/${path}/(?:([^/]+)).*$`);
                fallbackRoutes.push({
                    keys: [{ name: ViewContextLegacyParameter[context], optional: false }],
                    regexp,
                    template
                });
            }
        }
        /**
         * When asset detail routes (/device/:id,  /group/:id) are matched in Angular Router, ngRoute in
         * angular.js must also have matching generic routes so that the ids can be extracted from the paths and
         * injected in multiple calls (showIf, c8yActions, etc) as properties of $routeParams.
         *
         * The function in src/ngRoute/route.js (angular.js) where the routes are matched is called parseRoute(). This
         * function calls angular.forEach and in turn this function checks for the presence of a forEach method before
         * trying object key iteration.
         * By attaching a non enumerable forEach method to the routes object we guarantee that the fallback generic routes
         * are only matched after any other registered through $routeProvider.when.
         */
        const $route = this.injector.get('$route');
        Object.defineProperty($route.routes, 'forEach', {
            // make non enumerable
            value: function forEach(iterator, context) {
                // tslint:disable-next-line: forin
                for (const key in this) {
                    iterator.call(context, this[key], key, this);
                }
                fallbackRoutes.forEach(r => iterator.call(context, r));
            },
            configurable: true
        });
        /**
         * Some functions use the current context. As some parts are upgraded and some not, the following updates the
         * angularjs getContext function to resolve always the right context.
         */
        const c8yUiUtil = this.injector.get('c8yUiUtil');
        const _getContext = c8yUiUtil.getContext;
        this.router.events
            .pipe(filter(event => event instanceof ActivationEnd))
            .subscribe((event) => {
            if (event.snapshot.routeConfig.path === '**') {
                c8yUiUtil.getContext = _getContext;
            }
            else if (event.snapshot.data && event.snapshot.data.context) {
                c8yUiUtil.getContext = () => {
                    return {
                        context: event.snapshot.data.context.replace('/:id', ''),
                        id: event.snapshot.data.contextData.id,
                        contextData: event.snapshot.data.contextData
                    };
                };
            }
            else {
                c8yUiUtil.getContext = () => ({ context: null, id: null });
            }
        });
    }
    fixE2eIssues() {
        try {
            const { ngZone } = this;
            const { Utils } = window.org.cometd;
            const timeoutFn = Utils.setTimeout;
            // tslint:disable-next-line:only-arrow-functions
            Utils.setTimeout = function (...args) {
                return ngZone.runOutsideAngular(() => timeoutFn.apply(Utils, args));
            };
        }
        catch (e) {
            // do nothing
        }
        try {
            const { ace } = window;
            const editFn = ace.edit;
            const { ngZone } = this;
            // tslint:disable-next-line:only-arrow-functions
            ace.edit = function (...args) {
                return ngZone.runOutsideAngular(() => editFn.apply(ace, args));
            };
        }
        catch (e) {
            // do nothing
        }
    }
    hookLanguage() {
        let first = true;
        this.appState
            .map(store => store.lang)
            .subscribe(lang => {
            this.injector.get('c8yLocales').switchToLanguage(lang);
            if (!first) {
                this.injector.get('$rootScope').$apply();
            }
            first = false;
        });
    }
    hookTab() {
        // Just for instantiation of the c8yAction service
        this.injector.get('c8yActions');
        const $location = this.injector.get('$location');
        const c8yTabs = this.injector.get('c8yTabs');
        let liveTabs = [];
        c8yTabs.addTab = tab => {
            liveTabs.push({
                ...tab,
                label: tab.label || tab.name,
                path: decodeURIComponent(tab.path)
            });
            this.$liveTabs.next(liveTabs);
        };
        this.$ng1RouteChangeStart.subscribe(() => {
            liveTabs = [];
            this.$liveTabs.next(liveTabs);
        });
        const syncRouters = () => {
            const path = $location.path();
            // Don't sync if Angular Router is using secondary outlets
            // (e.g., /device/123/(dashboard-details:general))
            // Let Angular Router handle these advanced navigation scenarios
            if (this.router.url.includes('(') && this.router.url.includes(':')) {
                return;
            }
            // Only sync if paths differ and initial navigation is complete
            if (this.router.url !== path && this.initialNavigationDone) {
                this.router.navigate(path === '/' ? '' : path.split('/'), {
                    queryParams: $location.search(),
                    skipLocationChange: true
                });
            }
            if (this.actionService) {
                this.actionService.refresh();
            }
        };
        // Listen to $routeChangeSuccess (full navigation - always sync)
        this.$ng1RouteChangeSuccess.subscribe(syncRouters);
        // Listen to $routeUpdate (skip if query-param-only)
        this.$ng1RouteUpdate
            .pipe(filter(() => {
            const path = $location.path();
            const angularPath = this.router.url.split('?')[0];
            // Only process if path actually changed (not just query params)
            return angularPath !== path;
        }))
            .subscribe(syncRouters);
        this.$routeChanges = merge(this.$ng1RouteChangeSuccess, this.fromNg1Event(c8yTabs, c8yTabs.EVENT_UPDATE), of(1)).pipe(debounceTime(100));
    }
    hookNavigator() {
        this.navigationNodes$ = this.injector.get('c8yNavigator').rootNodes$;
    }
    getTabs() {
        const onlyVisible = ({ show }) => show;
        const upgradeTab = tab => ({
            ...tab,
            label: tab.label || tab.name,
            path: decodeURIComponent(tab.path)
        });
        const routeTabs = this.$routeChanges.pipe(switchMap(() => {
            const routes = this.injector.get('c8yTabs').routeTabs;
            const visibilityPromise = Promise.all(routes.map(({ checkingVisibility }) => checkingVisibility));
            return visibilityPromise.then(() => routes.filter(onlyVisible).map(upgradeTab));
        }), startWith([]));
        return combineLatest([routeTabs, this.$liveTabs]).pipe(map$1(([route, live]) => route.concat(live)));
    }
    getQuickLinks() {
        const c8yQuickLinks = this.injector.get('c8yQuickLinks');
        return c8yQuickLinks.list();
    }
    getActionBarItems() {
        const c8yActionBar = this.injector.get('c8yActionBar');
        const $rootScope = this.injector.get('$rootScope');
        const getActionBarElements = () => c8yActionBar.elements.map(element => ({
            priority: element.getAttribute('action-bar-priority') || 0,
            template: element,
            placement: element.getAttribute('action-bar-position') || 'right'
        }));
        return this.fromNg1Event($rootScope, 'c8yActionBarChanged').pipe(startWith(1), map$1(getActionBarElements));
    }
    getBreadcrumbs() {
        const $location = this.injector.get('$location');
        const c8yBreadcrumbs = this.injector.get('c8yBreadcrumbs');
        const breadcrumbsUpdate$ = new Observable(subscriber => c8yBreadcrumbs.$on('update', () => subscriber.next(null)));
        return breadcrumbsUpdate$.pipe(startWith(0), switchMap(() => {
            const path = $location.path();
            const breadcrumbs = c8yBreadcrumbs.get(path) || {};
            const breadcrumbsData = this.resolveBreadcrumbsData(breadcrumbs.data);
            return from(breadcrumbsData).pipe(map$1((value) => {
                const liveBreadcrumbs = c8yBreadcrumbs.getLiveBreadcrumbs();
                value = value.concat(liveBreadcrumbs);
                return value.map(items => ({ items: items }));
            }));
        }));
    }
    resolveBreadcrumbsData(data) {
        try {
            return this.injector.invoke(data);
        }
        catch (ex) {
            // empty
        }
        if (isArray(data)) {
            return of([data]);
        }
        return of([]);
    }
    getSearch() {
        const c8ySearch = this.injector.get('c8ySearch');
        return c8ySearch.list().map(item => {
            return {
                icon: 'search',
                name: item.name,
                term: '',
                onSearch() {
                    if (this.term) {
                        c8ySearch.search(this.term);
                    }
                }
            };
        });
    }
    getActions() {
        const registeredActions = this.injector.get('c8yActions').registeredActions;
        return of(registeredActions
            .filter(action => !action.hidden)
            .map(action => ({
            // The priority was reversed: Aligned it to dashboard, high first, low last.
            priority: (action.priority || 0) * -1,
            label: action.text,
            icon: action.icon,
            disabled: action.disabled,
            action: () => {
                this.injector.invoke(action.action, action);
            }
        })));
    }
    fromNg1Event(obj, evt) {
        let stopListening;
        function add(handler) {
            stopListening = obj.$on(evt, handler);
        }
        return fromEventPattern(add, () => stopListening());
    }
    hookUserMenu() {
        const userMenuService = this.injector.get('c8yUserMenuService');
        const c8yAccessDenied = this.injector.get('c8yAccessDenied');
        userMenuService.add({
            icon: 'access',
            priority: 10,
            label: gettext('Access denied requests'),
            click: c8yAccessDenied.showAccessDeniedRequestsList
        });
    }
}
function bridgeServiceFactory(injector, appState, router, ngZone, routerService, actionService) {
    return new BridgeService(injector, appState, router, ngZone, routerService, actionService);
}
const bridgeServiceProvider = {
    provide: BridgeService,
    useFactory: bridgeServiceFactory,
    deps: [
        '$injector',
        AppStateService,
        Router,
        NgZone,
        RouterService,
        ActionService,
        PluginsResolveService
    ]
};

class Ng1ActionBarFactoryService {
    constructor(bridge) {
        this.bridge = bridge;
        this.routeChanges$ = bridge.$routeChanges;
        this.$ng1RouteChangeSuccess = bridge.$ng1RouteChangeSuccess;
    }
    get() {
        return this.routeChanges$.pipe(switchMap(() => {
            return this.bridge.getActionBarItems();
        }));
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Ng1ActionBarFactoryService, deps: [{ token: BridgeService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Ng1ActionBarFactoryService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Ng1ActionBarFactoryService, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: BridgeService }] });

class Ng1ActionFactoryService {
    constructor(bridge, tabs) {
        this.bridge = bridge;
        this.tabs = tabs;
        this.routeChanges$ = bridge.$routeChanges;
        this.$location = bridge.injector.get('$location');
        this.tabs.items$.subscribe(newTabs => this.handleTabsRedirect(newTabs));
    }
    handleTabsRedirect(tabs) {
        /**
         * This function is doing the same process as function redirect in the file
         * modules/core/ui/navigation/tabs.provider.js
         * That function  is not run because bridge.service.ts overrides the method addTab where the redirect() was called.
         */
        const redirectedTab = tabs.find(tab => tab.redirectedTo);
        const [topPriorityTab] = tabs;
        if (redirectedTab && !topPriorityTab.redirectedTo) {
            this.$location.replace();
            this.$location.path(topPriorityTab.path);
            topPriorityTab.redirectedTo = true;
            redirectedTab.redirectedTo = false;
        }
    }
    get() {
        return this.bridge.getActions();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Ng1ActionFactoryService, deps: [{ token: BridgeService }, { token: i1.TabsService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Ng1ActionFactoryService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Ng1ActionFactoryService, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: BridgeService }, { type: i1.TabsService }] });

class AuthBridgeService {
    constructor(injector, basicAuth, fetchClient, appState, tenantUiService) {
        this.injector = injector;
        this.basicAuth = basicAuth;
        this.fetchClient = fetchClient;
        this.appState = appState;
        this.tenantUiService = tenantUiService;
        this.hookAuth();
    }
    updateBasicAuth(credentials) {
        const { headers } = this.fetchClient.getFetchOptions({});
        if (headers.Authorization) {
            const token = headers.Authorization.match(/basic\s(.*)$/i)[1];
            if (token) {
                this.basicAuth.updateCredentials(credentials);
                this.fetchClient.setAuth(this.basicAuth);
            }
        }
    }
    hookAuth() {
        this.appState.currentUser.subscribe(user => {
            if (!user) {
                this.injector.get('$rootScope').$emit('authStateChange', { hasAuth: false });
                return;
            }
            this.injector.get('c8yAuth').headers = () => this.fetchClient.getFetchOptions({}).headers;
            const { headers } = this.fetchClient.getFetchOptions({});
            const authorizationHeader = headers.Authorization;
            if (typeof authorizationHeader === 'string' && authorizationHeader.startsWith('Basic')) {
                const matches = authorizationHeader.match(/basic\s(.*)$/i);
                const token = matches && matches[1];
                if (token) {
                    this.setToken(token, headers.tfatoken);
                }
            }
            else if (typeof authorizationHeader === 'string' &&
                authorizationHeader.startsWith('Bearer')) {
                const matches = authorizationHeader.match(/bearer\s(.*)$/i);
                const token = matches && matches[1];
                if (token) {
                    this.setToken(token, headers.tfatoken, 'Bearer');
                }
            }
            else {
                this.setToken(undefined, headers.tfatoken, 'Oauth');
            }
            this.injector.get('$rootScope').$emit('authStateChange', { hasAuth: true });
        });
    }
    setToken(token, tfa, type = 'Basic') {
        const c8yAuth = this.injector.get('c8yAuth');
        if (type === 'Basic' || type === 'Bearer') {
            c8yAuth.onSetToken({ token, type });
            if (tfa) {
                c8yAuth.setTFAToken(tfa);
            }
        }
        else {
            c8yAuth.authReady();
        }
    }
    getPreferredLoginOption() {
        return this.tenantUiService.getPreferredLoginOption(this.appState.state.loginOptions);
    }
}
function authBridgeServiceFactory(injector, basicAuth, fetchClient, appState, tenantUiService) {
    return new AuthBridgeService(injector, basicAuth, fetchClient, appState, tenantUiService);
}
const authBridgeServiceProvider = {
    provide: AuthBridgeService,
    useFactory: authBridgeServiceFactory,
    deps: ['$injector', BasicAuth, FetchClient, AppStateService, TenantUiService]
};

class Ng1BreadcrumbFactoryService {
    constructor(bridge) {
        this.bridge = bridge;
        this.trigger = new ReplaySubject(1);
        this.breadcrumbs = this.trigger.pipe(debounceTime(100), switchMap(() => {
            return this.bridge.getBreadcrumbs();
        }));
    }
    get() {
        this.trigger.next();
        return this.breadcrumbs;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Ng1BreadcrumbFactoryService, deps: [{ token: BridgeService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Ng1BreadcrumbFactoryService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Ng1BreadcrumbFactoryService, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: BridgeService }] });

class Ng1DocsFactoryService {
    constructor(bridge) {
        this.bridge = bridge;
        this.links = this.bridge.getQuickLinks();
        this.links.then(list => {
            list.map(el => {
                el.type = el.type || 'quicklink';
                return el;
            });
        });
    }
    get() {
        return this.links;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Ng1DocsFactoryService, deps: [{ token: BridgeService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Ng1DocsFactoryService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Ng1DocsFactoryService, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: BridgeService }] });

class Ng1NodesFactoryService {
    constructor(bridge) {
        this.bridge = bridge;
    }
    get() {
        return this.bridge.navigationNodes$;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Ng1NodesFactoryService, deps: [{ token: BridgeService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Ng1NodesFactoryService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Ng1NodesFactoryService, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: BridgeService }] });

class Ng1TabsFactoryService {
    constructor(bridge) {
        this.bridge = bridge;
        this.tabsObservable = bridge.getTabs();
    }
    get() {
        return this.tabsObservable;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Ng1TabsFactoryService, deps: [{ token: BridgeService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Ng1TabsFactoryService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Ng1TabsFactoryService, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: BridgeService }] });

setAngularJSGlobal(angular);
class UpgradeModule {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: UpgradeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.16", ngImport: i0, type: UpgradeModule, imports: [RouterModule, UpgradedServicesModule] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: UpgradeModule, providers: [
            absoluteDateServiceProvider,
            bridgeServiceProvider,
            authBridgeServiceProvider,
            hookNavigator(Ng1NodesFactoryService),
            hookTab(Ng1TabsFactoryService),
            hookActionBar(Ng1ActionBarFactoryService),
            hookAction(Ng1ActionFactoryService),
            hookBreadcrumb(Ng1BreadcrumbFactoryService),
            hookDocs(Ng1DocsFactoryService)
        ], imports: [RouterModule, UpgradedServicesModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: UpgradeModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [RouterModule, UpgradedServicesModule],
                    exports: [],
                    providers: [
                        absoluteDateServiceProvider,
                        bridgeServiceProvider,
                        authBridgeServiceProvider,
                        hookNavigator(Ng1NodesFactoryService),
                        hookTab(Ng1TabsFactoryService),
                        hookActionBar(Ng1ActionBarFactoryService),
                        hookAction(Ng1ActionFactoryService),
                        hookBreadcrumb(Ng1BreadcrumbFactoryService),
                        hookDocs(Ng1DocsFactoryService)
                    ]
                }]
        }] });

function c8yAlertDecorator($delegate, $rootScope, $injector) {
    'ngInject';
    $delegate.add = alert => {
        $delegate.addAlert(transformAlert(alert));
    };
    $rootScope.$on('alert', (evt, alert) => {
        $delegate.addAlert(transformAlert(alert));
    });
    $rootScope.$on('message', (evt, alert) => {
        $delegate.addAlert(transformAlert(alert));
    });
    /**
     * Solution based on the: https://stackoverflow.com/questions/40102148/how-to-iterate-over-all-properties-in-objects-prototype-chain.
     * Problem came after switching to ES6, as all prototype properties of classes are non-enumerable.
     */
    const allNames = new Set();
    for (let o = $delegate; o !== Object.prototype; o = Object.getPrototypeOf(o)) {
        for (const name of Object.getOwnPropertyNames(o)) {
            allNames.add(name);
        }
    }
    Array.from(allNames).forEach((property) => {
        if (typeof $delegate[property] === 'function') {
            $delegate[property] = $delegate[property].bind($delegate);
        }
    });
    function transformAlert(alert) {
        const newAlert = { ...alert };
        if (alert.onClose) {
            newAlert.onClose = () => {
                $injector.invoke(alert.onClose);
            };
        }
        if (alert.onDetail) {
            newAlert.onDetail = () => {
                $injector.invoke(alert.onDetail);
            };
        }
        return newAlert;
    }
    return $delegate;
}

const bootstrapComponentDowngradedComponent = downgradeComponent({
    component: BootstrapComponent
});
const userTotpComponentDowngradedComponent = downgradeComponent({
    component: UserTotpRevokeComponent
});
const appLogsAutoRefreshComponentDowngradedComponent = downgradeComponent({
    component: AppLogsAutoRefreshComponent
});
const dataGridComponentDowngradedComponent = downgradeComponent({
    component: DataGridComponent
});
const loadingComponentDowngradedComponent = downgradeComponent({
    component: LoadingComponent
});
const rangeDisplayComponentDowngradedComponent = downgradeComponent({
    component: RangeDisplayComponent
});
const helpComponentDowngradedComponent = downgradeComponent({ component: HelpComponent });
const highlightComponentDowngradedComponent = downgradeComponent({
    component: HighlightComponent,
    inputs: ['pattern', 'text']
});
const emptyStateComponentDowngradedComponent = downgradeComponent({
    component: EmptyStateComponent
});
const datapointSelectionListComponentDowngradedComponent = downgradeComponent({
    component: DatapointSelectionListComponent
});
const paginationComponentDowngradedComponent = downgradeComponent({
    component: PaginationComponent
});
const rolesAssetTreeComponentDowngradedComponent = downgradeComponent({
    component: RolesAssetTreeComponent
});
const passwordInputComponentDowngradedComponent = downgradeComponent({
    component: PasswordInputComponent
});
const platformConfigurationFormDowngradedComponent = downgradeComponent({
    component: PlatformConfigurationFormComponent
});
const globalContextWidgetWrapperDowngradedComponent = downgradeComponent({
    component: GlobalContextWidgetWrapperComponent,
    inputs: [
        'widgetControls',
        'displayMode',
        'isLoading',
        'config',
        'controlLinks',
        'dashboardChildForLegacy'
    ],
    outputs: ['onChange']
});
const widgetPreviewWrapperDowngradedComponent = downgradeComponent({
    component: WidgetPreviewWrapperComponent
});

class ServerMessagesService {
    constructor(translateService, patterns) {
        this.translateService = translateService;
        this.MESSAGE_PATTERNS = patterns;
    }
    translate(s) {
        return this.translateService.instant(s);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ServerMessagesService, deps: [{ token: i1$1.TranslateService }, { token: HOOK_PATTERN_MESSAGES }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ServerMessagesService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ServerMessagesService, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: i1$1.TranslateService }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [HOOK_PATTERN_MESSAGES]
                }] }] });

const absoluteDateServiceDowngradedInjectable = downgradeInjectable(AbsoluteDateService);
const widgetConfigMigrationServiceDowngradedInjectable = downgradeInjectable(WidgetConfigMigrationService);
const widgetConfigServiceDowngradedInjectable = downgradeInjectable(WidgetConfigService);
const bridgeServiceDowngradedInjectable = downgradeInjectable(BridgeService);
const authBridgeServiceDowngradedInjectable = downgradeInjectable(AuthBridgeService);
const appStateServiceDowngradedInjectable = downgradeInjectable(AppStateService);
const headerServiceDowngradedInjectable = downgradeInjectable(HeaderService);
const alertsServiceDowngradedInjectable = downgradeInjectable(AlertService);
const userMenuServiceDowngradedInjectable = downgradeInjectable(UserMenuService);
const apiServiceDowngradedInjectable = downgradeInjectable(ApiService);
const docsServiceDowngradedInjectable = downgradeInjectable(DocsService);
const passwordServiceDowngradedInjectable = downgradeInjectable(PasswordService);
const translateServiceDowngradedInjectable = downgradeInjectable(TranslateService);
const cachedLocaleDictionaryServiceDowngradedInjectable = downgradeInjectable(CachedLocaleDictionaryService);
const globalConfigServiceDowngradedInjectable = downgradeInjectable(GlobalConfigService);
const serverMessagesServiceDowngradedInjectable = downgradeInjectable(ServerMessagesService);
const modalServiceDowngradedInjectable = downgradeInjectable(ModalService);
const changeCurrentUserPasswordServiceDowngradedInjectable = downgradeInjectable(ChangeCurrentUserPasswordService);
const gainsightServiceDowngradedInjectable = downgradeInjectable(GainsightService);
const filesServiceDowngradedInjectable = downgradeInjectable(FilesService);
const deviceTypeDetailEditedServiceDowngradedInjectable = downgradeInjectable(DeviceTypeDetailEditedService);
const deviceGridServiceDowngradedInjectable = downgradeInjectable(DeviceGridService);
const serviceRegistryInjectable = downgradeInjectable(ServiceRegistry);
const assetLinkPipeDowngradedInjectable = downgradeInjectable(AssetLinkPipe);
const propertyValueTransformServiceDowngradedInjectable = downgradeInjectable(PropertyValueTransformService);
const featureCacheServiceDowngradedInjectable = downgradeInjectable(FeatureCacheService);
const datapointSelectorServiceDowngradedInjectable = downgradeInjectable(DatapointSelectorService);
const dateFormatServiceInjectable = downgradeInjectable(DateFormatService);

function gettextCatalogDecorator($delegate, $interpolate, c8yTranslate) {
    'ngInject';
    const gettextCatalog = $delegate;
    const originalGetString = angular.bind(gettextCatalog, gettextCatalog.getString);
    function newGetString(input, scope, context) {
        if (typeof input === 'string') {
            const translatedString = originalGetString(input, scope, context);
            const interpolatedString = scope ? $interpolate(input)(scope) : input;
            let stringToReturn = translatedString;
            if (translatedString && translatedString === interpolatedString) {
                const translatedServerMessage = c8yTranslate.instant(interpolatedString);
                stringToReturn = translatedServerMessage;
            }
            return stringToReturn;
        }
        return input;
    }
    gettextCatalog.getString = newGetString;
    return gettextCatalog;
}

function groupTypesHierarchyNavigatorDecorator($delegate, $q) {
    'ngInject';
    $delegate.loadAll = () => $q.when();
    $delegate.addGroupNavigation = () => $q.when();
    return $delegate;
}

function c8yNg1HttpInterceptor($q, c8yLoadingIndicator, c8yApiService) {
    'ngInject';
    function request(config) {
        const { url, method } = config;
        c8yApiService.onStart({ url, method, options: config });
        return config;
    }
    function requestError(rejection) {
        finishRequest(rejection);
        return $q.reject(rejection);
    }
    function response(res) {
        finishRequest(res);
        return res;
    }
    function responseError(rejection) {
        finishRequest(rejection);
        c8yLoadingIndicator.responseError(rejection);
        return $q.reject(rejection);
    }
    function finishRequest(res) {
        const { url, method } = res.config;
        c8yApiService.onFinish({
            url,
            method,
            response: res,
            options: res.config
        });
    }
    return {
        request,
        requestError,
        response,
        responseError
    };
}

class NavigatorNodeRootLegacy extends NavigatorNodeRoot {
    addRoot(nodeData) {
        let duplicate;
        if (nodeData.path === '') {
            nodeData.path = '/';
        }
        nodeData.label = nodeData.name;
        if (typeof nodeData.parent === 'object') {
            nodeData.parent.label = nodeData.parent.name;
        }
        if (nodeData.preventDuplicates) {
            duplicate = this.find(({ path, parents, label }) => {
                return (path === nodeData.path &&
                    label === nodeData.label &&
                    parents.some(p => p.label === nodeData.parent));
            });
            if (duplicate) {
                duplicate.routerLinkExact = false;
            }
        }
        return duplicate || super.addRoot(nodeData);
    }
    createNode(node) {
        const newNode = super.createNode(node);
        const update = newNode.update.bind(newNode);
        // eslint-disable-next-line @typescript-eslint/no-this-alias
        const root = this;
        return Object.defineProperties(assign(newNode, {
            realName: newNode.name || newNode.label,
            _parent: true, // just use it to detect if it has been deleted
            update(data) {
                if (this._parent === undefined) {
                    // _parent was deleted somene instead to put this in root
                    root.addRoot(this);
                    // put it back so it can be deleted again
                    this._parent = true;
                }
                update(data);
            },
            addChild(nodeChild) {
                this.add(root.createNode(nodeChild));
            }
        }), {
            label: {
                get() {
                    return this.realName || '';
                },
                set(name) {
                    this.realName = name;
                }
            },
            name: {
                get() {
                    return this.realName || '';
                },
                set(name) {
                    this.realName = name;
                }
            },
            show: {
                get() {
                    return !this.hidden;
                },
                set(show) {
                    this.hidden = !show;
                },
                configurable: true
            }
        });
    }
}

// Just to hook into the bridge service
function c8yNavigatorProvider() {
    const root = new NavigatorNodeRootLegacy();
    const rootNodesSubject = new Subject();
    const conditionalNodes = [];
    const rootNodes$ = rootNodesSubject.pipe(merge$1(defer(() => of(root.children))));
    function addNavigation(nodes) {
        const nodeList = Array.isArray(nodes) ? nodes : [nodes];
        nodeList.forEach(node => {
            if (isConditional(node)) {
                node.hidden = undefined;
                conditionalNodes.push(node);
            }
            node.navNode = root.addRoot(node);
        });
        rootNodesSubject.next(root.children);
    }
    function removeNavigation(node) {
        const found = root.find(n => n === node);
        if (found) {
            found.parents.forEach(p => p.remove(found));
            rootNodesSubject.next(root.children);
        }
    }
    function findNode(node) {
        return root.find(node);
    }
    function isConditional(node) {
        return node.showIf || node.showIfPermissions || node.showIfContainsVisibleViews;
    }
    function $get($q, $injector) {
        'ngInject';
        // This avoids the circular dependency
        setTimeout(() => conditionalNodes.forEach(processShowIf));
        function processShowIf(node) {
            const c8yUiUtil = $injector.get('c8yUiUtil');
            const visibilityPromises = [];
            const { showIf, showIfPermissions, showIfContainsVisibleViews } = node;
            if (showIf) {
                visibilityPromises.push($injector.invoke(showIf));
            }
            if (showIfContainsVisibleViews) {
                visibilityPromises.push(viewsConditionalVisibility(node));
            }
            c8yUiUtil
                .configureVisibility({
                showIf: () => $q.all(visibilityPromises).then(every),
                showIfPermissions
            }, 'visible')
                .then(({ visible }) => {
                if (visible) {
                    node.navNode.update({
                        hidden: false,
                        showIf: null,
                        showIfPermission: null,
                        showIfContainsVisibleViews: null
                    });
                }
                else {
                    node.navNode.update({
                        hidden: true
                    });
                }
            });
        }
        function viewsConditionalVisibility(node) {
            const c8yUiUtil = $injector.get('c8yUiUtil');
            const c8yViews = $injector.get('c8yViews');
            const views = c8yViews.getByPath(node.path);
            return $q
                .all(map(views, view => c8yUiUtil
                .configureVisibility(pick(view, ['showIf', 'showIfPermissions']), 'show', false)
                .then(property('show'))))
                .then(some);
        }
        return {
            rootNodes() {
                return root.children;
            },
            findNode,
            addNavigation,
            removeNavigation,
            rootNodes$
        };
    }
    return {
        $get,
        addNavigation,
        removeNavigation
    };
}

const rootComponent = {
    template: `
  <c8y-bootstrap>
    <div id="c8y-legacy-view">
      <div ng-view ng-if="vm.widthSet && vm.authState.hasAuth"></div>
    </div>
  </c8y-bootstrap>`,
    controller: c8yUiRootController,
    controllerAs: 'vm'
};
function c8yUiRootController($rootScope, $timeout, c8yBase, c8yNavigator, c8yApplication, c8yHeaderService) {
    'ngInject';
    // eslint-disable-next-line @typescript-eslint/no-this-alias
    const vm = this;
    Object.assign(vm, {
        $onInit,
        navOpen: false
    });
    ////////////
    function $onInit() {
        c8yHeaderService
            .map(states => states.nav.open)
            .subscribe(isOpen => {
            vm.navOpen = isOpen;
        });
        c8yHeaderService.configNavigator({ canToggle: true });
        $rootScope.$on('authStateChange', onAuthStateChange);
        vm.rootNodes = c8yNavigator.rootNodes;
        c8yApplication.currentAppCached().then(onAppInfo);
        vm.navHiddenOnStartup = c8yBase.appOption('hide_navigator');
        checkReady();
    }
    function onAuthStateChange(evt, data) {
        vm.authState = data;
    }
    function onAppInfo() {
        vm.tabsHorizontal = c8yBase.appOption('tabsHorizontal');
    }
    function checkReady() {
        const element = document.querySelector('#c8y-legacy-view');
        const hasWidth = element && element.clientWidth;
        if (hasWidth) {
            vm.widthSet = true;
        }
        else {
            $timeout(checkReady);
        }
    }
}

function c8yTitleDecorator($q, $delegate, $injector, $rootScope, $location, $templateCache, $compile, c8yHeaderService) {
    'ngInject';
    $delegate.changeTitle = changeTitle;
    $delegate.setTitleElement = setTitleElement;
    $rootScope.$on('$routeChangeStart', () => {
        changeTitle({});
    });
    $rootScope.$on('$routeChangeSuccess', event => {
        resolveTitle(event);
    });
    $rootScope.$on('$routeUpdate', event => {
        resolveTitle(event);
    });
    function resolveTitle(event) {
        const title = $delegate.get($location.path());
        if (title) {
            const titleData = $q.when(title.data ? $injector.invoke(title.data) : {});
            titleData.then(data => {
                const { templateUrl } = data;
                if (templateUrl) {
                    const template = $templateCache.get(templateUrl);
                    setTitleElement($compile(template)(event.targetScope));
                }
                else {
                    changeTitle(data);
                }
            });
        }
    }
    function changeTitle(newTitleSubtitleObjOrPromise, options = { skipTitleTranslation: false, skipSubtitleTranslation: false }) {
        $q.when(newTitleSubtitleObjOrPromise).then(newTitleSubtitleObj => changeTitleInAngular(translate(newTitleSubtitleObj, options)));
    }
    function translate({ title = '', subtitle = '' }, { skipTitleTranslation = false, skipSubtitleTranslation = false }) {
        const titleTemplate = skipTitleTranslation ? '{{ title }}' : '{{ title | translate }}';
        const subtitleTemplate = skipSubtitleTranslation
            ? '{{ subtitle }}'
            : '{{ subtitle | translate }}';
        const template = `
      <h1 class="text-truncate">${titleTemplate}
      <small>${subtitleTemplate}</small></h1>
    `;
        const isolatedScope = $rootScope.$new(true);
        isolatedScope.title = title;
        isolatedScope.subtitle = subtitle;
        return $compile(angular.element(template))(isolatedScope)[0];
    }
    function changeTitleInAngular(domElement) {
        c8yHeaderService.changeTitle(domElement);
    }
    function setTitleElement($element) {
        $element.show();
        changeTitleInAngular($element[0]);
    }
    return $delegate;
}

const NAME_UPGRADE = 'c8y.upgrade';
window.preventNg1Bootstrap = true;
angular
    .module(NAME_UPGRADE, [])
    // tslint:disable-next-line:only-arrow-functions
    .config(function ($httpProvider) {
    'ngInject';
    const ng1InterceptorIndex = $httpProvider.interceptors.indexOf('c8yLoadingIndicator');
    if (ng1InterceptorIndex > -1) {
        $httpProvider.interceptors.splice(ng1InterceptorIndex, 1);
    }
    $httpProvider.interceptors.push(c8yNg1HttpInterceptor);
})
    .component('c8yUiRoot', rootComponent)
    .directive('c8yBootstrap', bootstrapComponentDowngradedComponent)
    .factory('c8yBridgeService', bridgeServiceDowngradedInjectable)
    .factory('c8yAuthBridgeService', authBridgeServiceDowngradedInjectable)
    .factory('c8yAppStateService', appStateServiceDowngradedInjectable)
    .factory('c8yDateFormatService', dateFormatServiceInjectable)
    .factory('c8yHeaderService', headerServiceDowngradedInjectable)
    .factory('c8yUserMenuService', userMenuServiceDowngradedInjectable)
    // tslint:disable-next-line:only-arrow-functions
    .service('c8yQueriesUtil', function () {
    return new QueriesUtil();
})
    .factory('c8yAlert', alertsServiceDowngradedInjectable)
    .decorator('c8yAlert', c8yAlertDecorator)
    .decorator('groupTypesHierarchyNavigator', groupTypesHierarchyNavigatorDecorator) // prevents loading the groups
    .factory('c8yApiService', apiServiceDowngradedInjectable)
    .factory('c8yDocs', docsServiceDowngradedInjectable)
    .service('c8yPasswordConfirm', passwordServiceDowngradedInjectable)
    .service('c8yModalService', modalServiceDowngradedInjectable)
    .service('c8yChangeCurrentUserPasswordService', changeCurrentUserPasswordServiceDowngradedInjectable)
    .service('c8yGainsightService', gainsightServiceDowngradedInjectable)
    .service('c8yFilesService', filesServiceDowngradedInjectable)
    .service('c8yGlobalConfigService', globalConfigServiceDowngradedInjectable)
    .service('c8yPropertyValueTransformService', propertyValueTransformServiceDowngradedInjectable)
    .service('c8yFeatureCacheService', featureCacheServiceDowngradedInjectable)
    .service('c8yDatapointSelectorService', datapointSelectorServiceDowngradedInjectable)
    .service('c8yWidgetConfigMigrationService', widgetConfigMigrationServiceDowngradedInjectable)
    .service('c8yWidgetConfigService', widgetConfigServiceDowngradedInjectable);
angular
    .module('c8y.ui')
    .filter('absoluteDate', absoluteDateServiceDowngradedInjectable)
    .directive('c8yLoading', loadingComponentDowngradedComponent)
    .provider('c8yNavigator', c8yNavigatorProvider)
    .provider('c8yViews', c8yViewsProvider)
    .directive('c8yUserTotpRevoke', userTotpComponentDowngradedComponent)
    .directive('c8yAppLogsAutoRefresh', appLogsAutoRefreshComponentDowngradedComponent)
    .directive('c8yDataGrid', dataGridComponentDowngradedComponent)
    .directive('c8yRangeDisplay', rangeDisplayComponentDowngradedComponent)
    .directive('c8yHelp', helpComponentDowngradedComponent)
    .directive('c8yUiEmptyState', emptyStateComponentDowngradedComponent)
    .directive('c8yDatapointSelectionList', datapointSelectionListComponentDowngradedComponent)
    .directive('c8yHighlight', highlightComponentDowngradedComponent)
    .directive('c8yGlobalContextWidgetWrapper', globalContextWidgetWrapperDowngradedComponent)
    .directive('c8yPasswordInput', passwordInputComponentDowngradedComponent)
    .directive('pagination', paginationComponentDowngradedComponent)
    .directive('c8yRolesAssetTreeDowngraded', rolesAssetTreeComponentDowngradedComponent)
    .directive('c8yPlatformConfigurationForm', platformConfigurationFormDowngradedComponent)
    .directive('c8yWidgetPreviewWrapper', widgetPreviewWrapperDowngradedComponent)
    .factory('c8yTranslate', translateServiceDowngradedInjectable)
    .factory('c8yCachedLocaleDictionaryService', cachedLocaleDictionaryServiceDowngradedInjectable)
    .decorator('gettextCatalog', gettextCatalogDecorator)
    .factory('c8yServerMessages', serverMessagesServiceDowngradedInjectable)
    .factory('ngZone', downgradeInjectable(NgZone))
    .factory('c8yDeviceTypeDetailEdited', deviceTypeDetailEditedServiceDowngradedInjectable)
    .factory('c8yDeviceGridService', deviceGridServiceDowngradedInjectable)
    .factory('c8yServiceRegistry', serviceRegistryInjectable)
    .factory('assetLink', assetLinkPipeDowngradedInjectable);
angular
    .module('c8y.ui')
    .decorator('c8yTitle', c8yTitleDecorator)
    .run([
    'c8yTitle',
    function () {
        // needed to inject c8yTitle with decorator applied to it, to ensure displaying ng1 titles
    }
]);
const ng1ModulesUpgrade = ['app', NAME_UPGRADE];

class HybridAppModule {
    constructor() {
        this.ng1Modules = ng1ModulesUpgrade;
    }
    ngDoBootstrap() {
        window.bootstrap();
        this.upgrade.bootstrap(document.getElementById('app'), this.ng1Modules, { strictDi: false });
    }
}

const UPGRADE_ROUTES = [{ path: '**', component: EmptyComponent }];

class DashboardBridgeService {
    constructor() {
        this.ng1Injector = inject('$injector');
        this.zone = inject(NgZone);
        this.router = inject(Router);
        this.contextDashboardService = inject(ContextDashboardService, { optional: true });
        this.dashboardSvc = this.ng1Injector.get('dashboardSvc');
        this.compile = this.ng1Injector.get('$compile');
    }
    get ng1Components() {
        return this.ng1Injector.get('c8yComponents');
    }
    async instantiateComponent(widget, element, dashboardChild) {
        const { dashboard, context, child } = widget;
        if (dashboard) {
            const transformedChild = await this.dashboardSvc.transformChildWithContext(this.dashboardSvc.forcedContext || context, dashboard, child);
            if (this.dashboardSvc.forcedContext || dashboard.deviceType || dashboard.updateTarget) {
                await this.dashboardSvc.updateConfigTargetsWithContext(this.dashboardSvc.forcedContext || context, transformedChild.config);
            }
            return this.zone.runOutsideAngular(() => this.loadTemplate(transformedChild, child, element, context, dashboardChild));
        }
        else {
            return this.loadConfigTemplate(element, widget);
        }
    }
    instantiateDeviceSelector(element, widgetConfig) {
        return this.loadConfigTemplate(element, widgetConfig, true);
    }
    loadTemplate(transformedChild, child, element, context, dashboardChild) {
        const scope = this.ng1Injector.get('$rootScope').$new(true);
        scope.child = transformedChild;
        scope.dashboardContext = context;
        scope.dashboardChildForLegacy = dashboardChild;
        if (child.widgetComponent) {
            element.innerHTML = `<c8y-ui-component component-name="'${child.widgetComponent}'" config="child.config" context="dashboardContext"></c8y-ui-component>`;
        }
        else if (child.templateUrl) {
            element.innerHTML = `<ng-include src="'${child.templateUrl}'"></ng-include>`;
        }
        this.compile(element)(scope);
        return scope;
    }
    getDashboard() {
        return getActivatedRoute(this.router).snapshot.data.dashboard;
    }
    loadConfigTemplate(element, widgetConfig, onlyDeviceSelector = false) {
        const { settings } = widgetConfig;
        const scope = this.ng1Injector.get('$rootScope').$new(true);
        scope.settings = { ...settings, ...settings.ng1 };
        scope.options = widgetConfig.options;
        scope.config = widgetConfig;
        scope.forms = {};
        scope.rootId = settings.context.id;
        scope.dashboard = get(widgetConfig, 'settings.dashboardMo');
        let configCmp = '';
        if (!onlyDeviceSelector) {
            if (widgetConfig.settings.configComponent) {
                configCmp = `<c8y-ui-component component-name="'${widgetConfig.settings.configComponent}'" config="config"></c8y-ui-component>`;
            }
            else if (widgetConfig.settings.configTemplateUrl) {
                configCmp = `<ng-include src="'${widgetConfig.settings.configTemplateUrl}'"></ng-include>`;
            }
        }
        element.innerHTML = `
    <ng-form name="forms.componentForm">
      <div class="form-group m-0"
        ng-if="!settings.noDeviceTarget"
        ng-style="{overflow: 'hidden'}"
      >
      </div>
      ${configCmp}
    </ng-form>`;
        scope.$watch('forms.componentForm.$invalid', formStatus => {
            this.contextDashboardService.formDisabled = formStatus;
        });
        this.compile(element)(scope);
        this.contextDashboardService.formDisabled = scope.forms.componentForm.$invalid;
        return scope;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DashboardBridgeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DashboardBridgeService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DashboardBridgeService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [] });

class WidgetComponent {
    constructor(dashboard, dashboardBridgeService, el, dashboardChild) {
        this.dashboard = dashboard;
        this.dashboardBridgeService = dashboardBridgeService;
        this.el = el;
        this.dashboardChild = dashboardChild;
        this.DEBOUNCE_TIME_UNTIL_WIDGET_HAS_SNAPPED = 400;
    }
    onBeforeSave() {
        this.ng1Scope.$broadcast('saveWidget');
        return true;
    }
    async ngOnInit() {
        if (this.config) {
            if (this.config.child) {
                this.config.child.alerts = this.alerts;
            }
            this.ng1Scope = await this.dashboardBridgeService.instantiateComponent(this.config, this.el.nativeElement, this.dashboardChild);
            if (this.dashboard) {
                this.resizeSubscription = merge(this.dashboard.onChangeDashboard, this.dashboard.onResize)
                    .pipe(debounceTime$1(this.DEBOUNCE_TIME_UNTIL_WIDGET_HAS_SNAPPED))
                    .subscribe(() => {
                    this.ng1Scope.$broadcast('dashboardResize');
                });
            }
        }
    }
    ngOnDestroy() {
        if (this.ng1Scope) {
            this.ng1Scope.$destroy();
        }
        if (this.resizeSubscription) {
            this.resizeSubscription.unsubscribe();
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: WidgetComponent, deps: [{ token: i1.WidgetsDashboardComponent, optional: true }, { token: DashboardBridgeService }, { token: i0.ElementRef }, { token: i1.DashboardChildComponent, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: WidgetComponent, isStandalone: true, selector: "c8y-widget-legacy", ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: WidgetComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'c8y-widget-legacy',
                    template: '',
                    changeDetection: ChangeDetectionStrategy.OnPush
                }]
        }], ctorParameters: () => [{ type: i1.WidgetsDashboardComponent, decorators: [{
                    type: Optional
                }] }, { type: DashboardBridgeService }, { type: i0.ElementRef }, { type: i1.DashboardChildComponent, decorators: [{
                    type: Optional
                }] }] });

class LegacyDeviceSelectorComponent {
    constructor(dashboardBridgeService, el) {
        this.dashboardBridgeService = dashboardBridgeService;
        this.el = el;
    }
    async ngOnInit() {
        this.ng1Scope = this.dashboardBridgeService.instantiateDeviceSelector(this.el.nativeElement, this.config);
    }
    ngOnDestroy() {
        if (this.ng1Scope) {
            this.ng1Scope.$destroy();
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: LegacyDeviceSelectorComponent, deps: [{ token: DashboardBridgeService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: LegacyDeviceSelectorComponent, isStandalone: true, selector: "c8y-device-selector-legacy", ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: LegacyDeviceSelectorComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'c8y-device-selector-legacy',
                    template: '',
                    changeDetection: ChangeDetectionStrategy.OnPush
                }]
        }], ctorParameters: () => [{ type: DashboardBridgeService }, { type: i0.ElementRef }] });

class Ng1ComponentFactoryService {
    constructor(bridge) {
        this.bridge = bridge;
        this.components$ = of(1).pipe(switchMap(() => this.getComponents()), shareReplay(1), take(1));
    }
    get() {
        return this.components$;
    }
    async getComponents() {
        const ng1Components = await this.bridge.ng1Components.list();
        const components = ng1Components.map(cmp => {
            const resolve = {};
            if (cmp.options?.datapointAttributes && Array.isArray(cmp.options?.datapointAttributes)) {
                cmp.options?.datapointAttributes.forEach(attribute => (resolve[attribute] = DynamicDatapointsResolver));
            }
            if (cmp.options?.managedObjectAttributes &&
                Array.isArray(cmp.options?.managedObjectAttributes)) {
                cmp.options?.managedObjectAttributes.forEach(attribute => (resolve[attribute] = DynamicManagedObjectResolver));
            }
            const data = {
                settings: {
                    ...cmp.options,
                    configTemplateUrl: cmp.configTemplateUrl,
                    widgetComponent: cmp.widgetComponent,
                    configComponent: cmp.configComponent,
                    transformConfigWithContext: cmp.transformConfigWithContext || cmp.componentTransformConfigWithContext,
                    upgrade: true
                }
            };
            data.settings.templateUrl = cmp.templateUrl; // workaround as in object it creates build error
            data.displaySettings = cmp.displaySettings;
            return {
                id: cmp.name,
                label: cmp.nameDisplay || cmp.name,
                description: cmp.description,
                component: WidgetComponent,
                configComponent: WidgetComponent,
                previewImage: cmp.previewImage,
                errorStrategy: cmp.errorStrategy,
                resolve,
                data
            };
        });
        // add the device selector legacy component
        components.push({
            id: 'device.selector.legacy',
            label: 'Device selector',
            description: '',
            data: { settings: { noNewWidgets: true, upgrade: true } },
            component: LegacyDeviceSelectorComponent
        });
        return components;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Ng1ComponentFactoryService, deps: [{ token: DashboardBridgeService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Ng1ComponentFactoryService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Ng1ComponentFactoryService, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: DashboardBridgeService }] });

class DashboardUpgradeModule {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DashboardUpgradeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.16", ngImport: i0, type: DashboardUpgradeModule, imports: [CommonModule,
            C8yTranslateModule,
            AssetSelectorModule,
            LegacyDeviceSelectorComponent,
            WidgetComponent] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DashboardUpgradeModule, providers: [hookComponent(Ng1ComponentFactoryService)], imports: [CommonModule,
            C8yTranslateModule,
            AssetSelectorModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DashboardUpgradeModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [
                        CommonModule,
                        C8yTranslateModule,
                        AssetSelectorModule,
                        LegacyDeviceSelectorComponent,
                        WidgetComponent
                    ],
                    providers: [hookComponent(Ng1ComponentFactoryService)]
                }]
        }] });

/**
 * Generated bundle index. Do not edit.
 */

export { AuthBridgeService, BridgeService, DashboardBridgeService, DashboardUpgradeModule, HybridAppModule, LegacyDeviceSelectorComponent, Ng1ActionBarFactoryService, Ng1ActionFactoryService, Ng1BreadcrumbFactoryService, Ng1ComponentFactoryService, Ng1DocsFactoryService, Ng1NodesFactoryService, Ng1TabsFactoryService, UPGRADE_ROUTES, UpgradeModule, WidgetComponent, authBridgeServiceFactory, authBridgeServiceProvider, bridgeServiceFactory, bridgeServiceProvider, ng1ModulesUpgrade };
//# sourceMappingURL=c8y-ngx-components-upgrade.mjs.map
