import { ɵgetAllInstancesOf as _getAllInstancesOf, ɵisSupportedError as _isSupportedError, ɵzoneWrap as _zoneWrap, VERSION, ɵgetDefaultInstanceOf as _getDefaultInstanceOf, ɵAngularFireSchedulers as _AngularFireSchedulers } from '@angular/fire';
import { timer, from, of } from 'rxjs';
import { concatMap, distinct, filter, switchMap, map, groupBy, mergeMap, distinctUntilChanged, startWith, pairwise } from 'rxjs/operators';
import * as i0 from '@angular/core';
import { Injectable, Optional, InjectionToken, APP_INITIALIZER, NgModule, makeEnvironmentProviders, NgZone, Injector } from '@angular/core';
import { FirebaseApp, FirebaseApps } from '@angular/fire/app';
import { registerVersion } from 'firebase/app';
import { isSupported as isSupported$1, getAnalytics as getAnalytics$1, getGoogleAnalyticsClientId as getGoogleAnalyticsClientId$1, initializeAnalytics as initializeAnalytics$1, logEvent as logEvent$1, setAnalyticsCollectionEnabled as setAnalyticsCollectionEnabled$1, setConsent as setConsent$1, setCurrentScreen as setCurrentScreen$1, setDefaultEventParameters as setDefaultEventParameters$1, setUserId as setUserId$1, setUserProperties as setUserProperties$1, settings as settings$1 } from 'firebase/analytics';
export * from 'firebase/analytics';
import * as i2 from '@angular/platform-browser';
import * as i1$1 from '@angular/router';
import { ActivationEnd, ɵEmptyOutletComponent as _EmptyOutletComponent } from '@angular/router';
import * as i1 from '@angular/fire/auth';
import { authState } from '@angular/fire/auth';

class Analytics {
    constructor(analytics) {
        return analytics;
    }
}
const ANALYTICS_PROVIDER_NAME = 'analytics';
class AnalyticsInstances {
    constructor() {
        return _getAllInstancesOf(ANALYTICS_PROVIDER_NAME);
    }
}
const analyticInstance$ = timer(0, 300).pipe(concatMap(() => from(_getAllInstancesOf(ANALYTICS_PROVIDER_NAME))), distinct());

const isAnalyticsSupportedValueSymbol = '__angularfire_symbol__analyticsIsSupportedValue';
const isAnalyticsSupportedPromiseSymbol = '__angularfire_symbol__analyticsIsSupported';
globalThis[isAnalyticsSupportedPromiseSymbol] ||= isSupported$1().then(it => globalThis[isAnalyticsSupportedValueSymbol] = it).catch(() => globalThis[isAnalyticsSupportedValueSymbol] = false);
const isAnalyticsSupportedFactory = {
    async: () => globalThis[isAnalyticsSupportedPromiseSymbol],
    sync: () => {
        const ret = globalThis[isAnalyticsSupportedValueSymbol];
        if (ret === undefined) {
            throw new Error(_isSupportedError('Analytics'));
        }
        return ret;
    }
};

const isSupported = isAnalyticsSupportedFactory.async;

// DO NOT MODIFY, this file is autogenerated by tools/build.ts
const getAnalytics = _zoneWrap(getAnalytics$1, true);
const getGoogleAnalyticsClientId = _zoneWrap(getGoogleAnalyticsClientId$1, true);
const initializeAnalytics = _zoneWrap(initializeAnalytics$1, true);
const logEvent = _zoneWrap(logEvent$1, true);
const setAnalyticsCollectionEnabled = _zoneWrap(setAnalyticsCollectionEnabled$1, true);
const setConsent = _zoneWrap(setConsent$1, true);
const setCurrentScreen = _zoneWrap(setCurrentScreen$1, true);
const setDefaultEventParameters = _zoneWrap(setDefaultEventParameters$1, true);
const setUserId = _zoneWrap(setUserId$1, true);
const setUserProperties = _zoneWrap(setUserProperties$1, true);
const settings = _zoneWrap(settings$1, true);

class UserTrackingService {
    initialized;
    disposables = [];
    constructor(auth, zone, injector) {
        registerVersion('angularfire', VERSION.full, 'user-tracking');
        let resolveInitialized;
        this.initialized = zone.runOutsideAngular(() => new Promise(resolve => { resolveInitialized = resolve; }));
        // The APP_INITIALIZER that is making isSupported() sync for the sake of convenient DI
        // may not be done when services are initialized. Guard the functionality by first ensuring
        // that the (global) promise has resolved, then get Analytics from the injector.
        isSupported().then(() => {
            const analytics = injector.get(Analytics);
            if (analytics) {
                this.disposables = [
                    // TODO add credential tracking back in
                    authState(auth).subscribe(user => {
                        setUserId(analytics, user?.uid);
                        resolveInitialized();
                    }),
                ];
            }
            else {
                resolveInitialized();
            }
        });
    }
    ngOnDestroy() {
        this.disposables.forEach(it => it.unsubscribe());
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: UserTrackingService, deps: [{ token: i1.Auth }, { token: i0.NgZone }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: UserTrackingService });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: UserTrackingService, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: i1.Auth }, { type: i0.NgZone }, { type: i0.Injector }] });

const FIREBASE_EVENT_ORIGIN_KEY = 'firebase_event_origin';
const FIREBASE_PREVIOUS_SCREEN_CLASS_KEY = 'firebase_previous_class';
const FIREBASE_PREVIOUS_SCREEN_INSTANCE_ID_KEY = 'firebase_previous_id';
const FIREBASE_PREVIOUS_SCREEN_NAME_KEY = 'firebase_previous_screen';
const FIREBASE_SCREEN_CLASS_KEY = 'firebase_screen_class';
const FIREBASE_SCREEN_INSTANCE_ID_KEY = 'firebase_screen_id';
const FIREBASE_SCREEN_NAME_KEY = 'firebase_screen';
const OUTLET_KEY = 'outlet';
const PAGE_PATH_KEY = 'page_path';
const PAGE_TITLE_KEY = 'page_title';
const SCREEN_CLASS_KEY = 'screen_class';
const SCREEN_NAME_KEY = 'screen_name';
const SCREEN_VIEW_EVENT = 'screen_view';
const EVENT_ORIGIN_AUTO = 'auto';
const SCREEN_INSTANCE_DELIMITER = '#';
// this is an INT64 in iOS/Android but use INT32 cause javascript
let nextScreenInstanceID = Math.floor(Math.random() * (2 ** 32 - 1)) - 2 ** 31;
const knownScreenInstanceIDs = {};
const getScreenInstanceID = (params) => {
    // unique the screen class against the outlet name
    const screenInstanceKey = [
        params[SCREEN_CLASS_KEY],
        params[OUTLET_KEY]
    ].join(SCREEN_INSTANCE_DELIMITER);
    // eslint-disable-next-line no-prototype-builtins
    if (knownScreenInstanceIDs.hasOwnProperty(screenInstanceKey)) {
        return knownScreenInstanceIDs[screenInstanceKey];
    }
    else {
        const ret = nextScreenInstanceID++;
        knownScreenInstanceIDs[screenInstanceKey] = ret;
        return ret;
    }
};
const ɵscreenViewEvent = (router, title, componentFactoryResolver) => {
    const activationEndEvents = router.events.pipe(filter(e => e instanceof ActivationEnd));
    return activationEndEvents.pipe(switchMap(activationEnd => {
        // router parseUrl is having trouble with outlets when they're empty
        // e.g, /asdf/1(bob://sally:asdf), so put another slash in when empty
        const urlTree = router.parseUrl(router.url.replace(/(?:\().+(?:\))/g, a => a.replace('://', ':///')));
        const pagePath = urlTree.root.children[activationEnd.snapshot.outlet]?.toString() || '';
        const actualSnapshot = router.routerState.root.children.map(it => it).find(it => it.outlet === activationEnd.snapshot.outlet);
        if (!actualSnapshot) {
            return of(null);
        }
        let actualDeep = actualSnapshot;
        while (actualDeep.firstChild) {
            actualDeep = actualDeep.firstChild;
        }
        const screenName = actualDeep.pathFromRoot.map(s => s.routeConfig?.path).filter(it => it).join('/') || '/';
        const params = {
            [SCREEN_NAME_KEY]: screenName,
            [PAGE_PATH_KEY]: `/${pagePath}`,
            [FIREBASE_EVENT_ORIGIN_KEY]: EVENT_ORIGIN_AUTO,
            [FIREBASE_SCREEN_NAME_KEY]: screenName,
            [OUTLET_KEY]: activationEnd.snapshot.outlet
        };
        if (title) {
            params[PAGE_TITLE_KEY] = title.getTitle();
        }
        let component = actualSnapshot.component;
        if (component) {
            if (component === _EmptyOutletComponent) {
                let deepSnapshot = activationEnd.snapshot;
                // TODO when might there be mutple children, different outlets? explore
                while (deepSnapshot.firstChild) {
                    deepSnapshot = deepSnapshot.firstChild;
                }
                component = deepSnapshot.component;
            }
        }
        else {
            component = activationEnd.snapshot.component;
        }
        if (typeof component === 'string') {
            return of({ ...params, [SCREEN_CLASS_KEY]: component });
        }
        else if (component) {
            const componentFactory = componentFactoryResolver.resolveComponentFactory(component);
            return of({ ...params, [SCREEN_CLASS_KEY]: componentFactory.selector });
        }
        // lazy loads cause extra activations, ignore
        return of(null);
    }), filter(it => !!it), map(params => ({
        [FIREBASE_SCREEN_CLASS_KEY]: params[SCREEN_CLASS_KEY],
        [FIREBASE_SCREEN_INSTANCE_ID_KEY]: getScreenInstanceID(params),
        ...params
    })), groupBy(it => it[OUTLET_KEY]), mergeMap(it => it.pipe(distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)), startWith(undefined), pairwise(), map(([prior, current]) => prior ? {
        [FIREBASE_PREVIOUS_SCREEN_CLASS_KEY]: prior[SCREEN_CLASS_KEY],
        [FIREBASE_PREVIOUS_SCREEN_NAME_KEY]: prior[SCREEN_NAME_KEY],
        [FIREBASE_PREVIOUS_SCREEN_INSTANCE_ID_KEY]: prior[FIREBASE_SCREEN_INSTANCE_ID_KEY],
        ...current
    } : current))));
};
class ScreenTrackingService {
    disposable;
    constructor(router, title, componentFactoryResolver, zone, userTrackingService, injector) {
        registerVersion('angularfire', VERSION.full, 'screen-tracking');
        // The APP_INITIALIZER that is making isSupported() sync for the sake of convenient DI
        // may not be done when services are initialized. Guard the functionality by first ensuring
        // that the (global) promise has resolved, then get Analytics from the injector.
        isSupported().then(() => {
            const analytics = injector.get(Analytics);
            if (!router || !analytics) {
                return;
            }
            zone.runOutsideAngular(() => {
                this.disposable = ɵscreenViewEvent(router, title, componentFactoryResolver).pipe(switchMap(async (params) => {
                    if (userTrackingService) {
                        await userTrackingService.initialized;
                    }
                    return logEvent(analytics, SCREEN_VIEW_EVENT, params);
                })).subscribe();
            });
        });
    }
    ngOnDestroy() {
        if (this.disposable) {
            this.disposable.unsubscribe();
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: ScreenTrackingService, deps: [{ token: i1$1.Router, optional: true }, { token: i2.Title, optional: true }, { token: i0.ComponentFactoryResolver }, { token: i0.NgZone }, { token: UserTrackingService, optional: true }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: ScreenTrackingService });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: ScreenTrackingService, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: i1$1.Router, decorators: [{
                    type: Optional
                }] }, { type: i2.Title, decorators: [{
                    type: Optional
                }] }, { type: i0.ComponentFactoryResolver }, { type: i0.NgZone }, { type: UserTrackingService, decorators: [{
                    type: Optional
                }] }, { type: i0.Injector }] });

const PROVIDED_ANALYTICS_INSTANCES = new InjectionToken('angularfire2.analytics-instances');
function defaultAnalyticsInstanceFactory(provided, defaultApp) {
    if (!isAnalyticsSupportedFactory.sync()) {
        return null;
    }
    const defaultAnalytics = _getDefaultInstanceOf(ANALYTICS_PROVIDER_NAME, provided, defaultApp);
    return defaultAnalytics && new Analytics(defaultAnalytics);
}
function analyticsInstanceFactory(fn) {
    return (zone, injector) => {
        if (!isAnalyticsSupportedFactory.sync()) {
            return null;
        }
        const analytics = zone.runOutsideAngular(() => fn(injector));
        return new Analytics(analytics);
    };
}
const ANALYTICS_INSTANCES_PROVIDER = {
    provide: AnalyticsInstances,
    deps: [
        [new Optional(), PROVIDED_ANALYTICS_INSTANCES],
    ]
};
const DEFAULT_ANALYTICS_INSTANCE_PROVIDER = {
    provide: Analytics,
    useFactory: defaultAnalyticsInstanceFactory,
    deps: [
        [new Optional(), PROVIDED_ANALYTICS_INSTANCES],
        FirebaseApp,
    ]
};
class AnalyticsModule {
    constructor(_screenTrackingService, _userTrackingService) {
        registerVersion('angularfire', VERSION.full, 'analytics');
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: AnalyticsModule, deps: [{ token: ScreenTrackingService, optional: true }, { token: UserTrackingService, optional: true }], target: i0.ɵɵFactoryTarget.NgModule });
    static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.0", ngImport: i0, type: AnalyticsModule });
    static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: AnalyticsModule, providers: [
            DEFAULT_ANALYTICS_INSTANCE_PROVIDER,
            ANALYTICS_INSTANCES_PROVIDER,
            {
                provide: APP_INITIALIZER,
                useValue: isAnalyticsSupportedFactory.async,
                multi: true,
            }
        ] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: AnalyticsModule, decorators: [{
            type: NgModule,
            args: [{
                    providers: [
                        DEFAULT_ANALYTICS_INSTANCE_PROVIDER,
                        ANALYTICS_INSTANCES_PROVIDER,
                        {
                            provide: APP_INITIALIZER,
                            useValue: isAnalyticsSupportedFactory.async,
                            multi: true,
                        }
                    ]
                }]
        }], ctorParameters: () => [{ type: ScreenTrackingService, decorators: [{
                    type: Optional
                }] }, { type: UserTrackingService, decorators: [{
                    type: Optional
                }] }] });
function provideAnalytics(fn, ...deps) {
    registerVersion('angularfire', VERSION.full, 'analytics');
    return makeEnvironmentProviders([
        DEFAULT_ANALYTICS_INSTANCE_PROVIDER,
        ANALYTICS_INSTANCES_PROVIDER,
        {
            provide: APP_INITIALIZER,
            useValue: isAnalyticsSupportedFactory.async,
            multi: true,
        },
        {
            provide: PROVIDED_ANALYTICS_INSTANCES,
            useFactory: analyticsInstanceFactory(fn),
            multi: true,
            deps: [
                NgZone,
                Injector,
                _AngularFireSchedulers,
                FirebaseApps,
                ...deps,
            ],
        },
    ]);
}

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

export { Analytics, AnalyticsInstances, AnalyticsModule, ScreenTrackingService, UserTrackingService, analyticInstance$, getAnalytics, getGoogleAnalyticsClientId, initializeAnalytics, isSupported, logEvent, provideAnalytics, setAnalyticsCollectionEnabled, setConsent, setCurrentScreen, setDefaultEventParameters, setUserId, setUserProperties, settings, ɵscreenViewEvent };
//# sourceMappingURL=angular-fire-analytics.mjs.map
