import * as i0 from '@angular/core';
import { inject, LOCALE_ID, Injectable, InjectionToken, input, signal, Component, NgModule } from '@angular/core';
import { ActivatedRoute, Router, NavigationEnd } from '@angular/router';
import { SiBreadcrumbComponent } from '@siemens/element-ng/breadcrumb';
import { Subject, Observable } from 'rxjs';
import { filter, takeUntil } from 'rxjs/operators';

/**
 * Copyright (c) Siemens 2016 - 2026
 * SPDX-License-Identifier: MIT
 */
class SiBreadcrumbDefaultResolverService {
    locale = inject(LOCALE_ID).toString();
    /**
     * Method which resolves the route and creates the breadcrumb items from it.
     * Is called by the `si-breadcrumb-router-component` but can also be called manually in inheritance patterns.
     */
    resolve(route) {
        if (route.data.siBreadcrumb) {
            return this.resolveCustomRoutePart(route);
        }
        else {
            return this.resolveDefault(route);
        }
    }
    resolveCustomRoutePart(route) {
        if (route.data.siBreadcrumb) {
            const rawLinks = route.data.siBreadcrumb;
            return rawLinks.map(rl => ({
                title: this.calculateName(route, rl.title),
                link: rl.link ? this.calculateUrl(route, rl.link) : route.fragment
            }));
        }
        return;
    }
    resolveDefault(route) {
        const links = [];
        let currRoute = route;
        while (currRoute != null) {
            if (currRoute.data.siBreadcrumb) {
                links.unshift(...this.resolveCustomRoutePart(currRoute));
            }
            else if (currRoute.url.length > 0) {
                const routeUrl = this.getUrl(currRoute);
                const routeName = this.getName(currRoute);
                let link;
                if (links.length === 0) {
                    link = { title: routeName };
                }
                else {
                    link = { title: routeName, link: routeUrl };
                }
                links.unshift(link);
            }
            currRoute = currRoute.parent;
        }
        return links;
    }
    getUrl(route) {
        const parent = route.parent;
        let url;
        if (parent != null) {
            url = this.getUrl(parent);
        }
        else {
            url = '';
        }
        const currentRouteUrl = route.url.map(o => o.toString()).join('/');
        if (!url.endsWith('/')) {
            url = url + '/';
        }
        url = url + currentRouteUrl;
        return url;
    }
    getName(route) {
        let name = route.data.title ?? route.url[0].path;
        if (typeof name === 'object') {
            name = name[this.locale];
        }
        return this.calculateName(route, name);
    }
    calculateName(route, baseName) {
        return this.calculate(route, baseName, /{(\w+)}/g);
    }
    calculateUrl(route, baseName) {
        return this.calculate(route, baseName, /:(\w+)\/?/g, ':', '');
    }
    calculate(route, base, pattern, replaceStart = '{', replaceEnd = '}') {
        let name = base;
        const values = [];
        let finding;
        // tslint:disable-next-line:no-conditional-assignment
        while ((finding = pattern.exec(name)) != null) {
            values.push(finding[1]);
        }
        values.forEach(value => {
            let replace = this.findParam(route, value);
            if (route.data.replaceValues) {
                replace = route.data.replaceValues[replace] ?? replace;
            }
            name = name.replace(`${replaceStart}${value}${replaceEnd}`, replace);
        });
        return name;
    }
    findParam(route, paramKey) {
        return (route.paramMap.get(paramKey) ??
            (route.parent ? this.findParam(route.parent, paramKey) : paramKey));
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiBreadcrumbDefaultResolverService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiBreadcrumbDefaultResolverService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiBreadcrumbDefaultResolverService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }] });

/**
 * Copyright (c) Siemens 2016 - 2026
 * SPDX-License-Identifier: MIT
 */
/**
 * Injection token to provide your own `SiBreadcrumbResolverService` implementation.
 *
 * ```
 * providers: [{
 *   provide: SI_BREADCRUMB_RESOLVER_SERVICE,
 *   useClass: CustomBreadcrumbResolverService,
 * }]
 * ```
 */
const SI_BREADCRUMB_RESOLVER_SERVICE = new InjectionToken('si.breadcrumb.resolver.service', { providedIn: 'root', factory: () => inject(SiBreadcrumbDefaultResolverService) });

/**
 * Copyright (c) Siemens 2016 - 2026
 * SPDX-License-Identifier: MIT
 */
class SiBreadcrumbRouterComponent {
    /**
     * Aria label for the main breadcrumb navigation. Needed for a11y.
     *
     * @defaultValue 'breadcrumb'
     */
    ariaLabel = input('breadcrumb', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
    items = signal([], ...(ngDevMode ? [{ debugName: "items" }] : []));
    currentCalcUrl = signal(undefined, ...(ngDevMode ? [{ debugName: "currentCalcUrl" }] : []));
    nextRoute = new Subject();
    resolverService = inject(SI_BREADCRUMB_RESOLVER_SERVICE);
    route = inject(ActivatedRoute, { optional: true });
    router = inject(Router, { optional: true });
    routerSubscription;
    ngOnInit() {
        this.checkItems();
    }
    ngOnDestroy() {
        this.routerSubscription?.unsubscribe();
        this.nextRoute.next();
    }
    checkItems() {
        if (!this.routerSubscription && this.route && this.router) {
            this.routerSubscription = this.router.events
                .pipe(filter(e => e instanceof NavigationEnd))
                .subscribe(navigationEvent => {
                const event = navigationEvent;
                // Get the new url
                const newUrl = event.urlAfterRedirects || event.url;
                // Only update when url differs from previous url
                if (this.currentCalcUrl() !== newUrl) {
                    this.currentCalcUrl.set(newUrl);
                    this.nextRoute.next();
                    this.computePath();
                }
            });
            if (this.router.navigated) {
                this.currentCalcUrl.set(this.router.url);
                this.computePath();
            }
        }
    }
    computePath() {
        if (!this.route || !this.resolverService) {
            return;
        }
        // Get a snapshot of the all current activate routes
        const pathFromRoot = this.route.snapshot.pathFromRoot;
        // Find the child/leaf route that fits to the url
        const route = this.findRouteWithUrl(pathFromRoot, this.currentCalcUrl()?.split('?')[0] ?? '');
        if (route) {
            // Workaround to fix a bug that the route is null, in some cases
            const links$ = this.resolverService.resolve(route);
            if (links$ instanceof Observable) {
                links$.pipe(takeUntil(this.nextRoute)).subscribe(links => {
                    this.items.set([{ link: '/', title: '/' }, ...links]);
                });
            }
            else {
                this.items.set([{ link: '/', title: '/' }, ...links$]);
            }
        }
    }
    findRouteWithUrl(routes, url) {
        let result = null;
        for (const route of routes) {
            const routeUrl = this.getUrl(route);
            if (url === routeUrl && !route.data?.siBreadcrumbIgnore) {
                result = route;
                break;
            }
            else {
                result = this.findRouteWithUrl(route.children, url);
                if (result != null) {
                    break;
                }
            }
        }
        return result;
    }
    getUrl(route) {
        let url = '';
        for (const routeSegment of route.pathFromRoot) {
            const segmentUrl = routeSegment.url.map(o => o.toString()).join('/');
            if (!url.endsWith('/')) {
                url = url + '/';
            }
            url = url + segmentUrl;
        }
        return url;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiBreadcrumbRouterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.8", type: SiBreadcrumbRouterComponent, isStandalone: true, selector: "si-breadcrumb-router", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<si-breadcrumb [items]=\"items()\" [ariaLabel]=\"ariaLabel()\" />\n", dependencies: [{ kind: "component", type: SiBreadcrumbComponent, selector: "si-breadcrumb", inputs: ["items", "showRootAsText", "ariaLabel"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiBreadcrumbRouterComponent, decorators: [{
            type: Component,
            args: [{ selector: 'si-breadcrumb-router', imports: [SiBreadcrumbComponent], template: "<si-breadcrumb [items]=\"items()\" [ariaLabel]=\"ariaLabel()\" />\n" }]
        }], propDecorators: { ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });

/**
 * Copyright (c) Siemens 2016 - 2026
 * SPDX-License-Identifier: MIT
 */
class SiBreadcrumbRouterModule {
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiBreadcrumbRouterModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
    static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.0.8", ngImport: i0, type: SiBreadcrumbRouterModule, imports: [SiBreadcrumbRouterComponent], exports: [SiBreadcrumbRouterComponent] });
    static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiBreadcrumbRouterModule, imports: [SiBreadcrumbRouterComponent] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiBreadcrumbRouterModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [SiBreadcrumbRouterComponent],
                    exports: [SiBreadcrumbRouterComponent]
                }]
        }] });

/**
 * Copyright (c) Siemens 2016 - 2026
 * SPDX-License-Identifier: MIT
 */

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

export { SI_BREADCRUMB_RESOLVER_SERVICE, SiBreadcrumbDefaultResolverService, SiBreadcrumbRouterComponent, SiBreadcrumbRouterModule };
//# sourceMappingURL=siemens-element-ng-breadcrumb-router.mjs.map
