import { ApplicationConfig, importProvidersFrom, APP_INITIALIZER, LOCALE_ID } from "@angular/core";
import { provideRouter, RouteReuseStrategy, withComponentInputBinding, withHashLocation } from "@angular/router";
import { provideHttpClient, withXsrfConfiguration, HTTP_INTERCEPTORS, withInterceptorsFromDi } from "@angular/common/http";
import { provideAnimations } from "@angular/platform-browser/animations";
import { routes } from "./app.routes";
import { HttpServiceImpl } from "@wm/http";
import { SecurityService } from "@wm/security";
import { VariablesService, MetadataService } from "@wm/variables";
import { OAuthService } from "@wm/oAuth";
import { PageDirective{{#if enableSpa}}, SpaPageDirective{{/if}} } from "@wm/components/page";
import {
    {{#if enableSecurity}}AuthGuard, RoleGuard, {{/if}}
    AppJSProvider,
    AppVariablesProvider,
    ComponentRefProvider,
    PrefabConfigProvider,
    WmNgRouteReuseStrategy,
    CanDeactivateNgPageGuard,
    AppExtensionProvider,
    CustomwidgetConfigProvider,
    AppDefaultsService,
    AppExtensionJSResolve,
    AppJSResolve,
    AppVariablesResolve,
    AppBeforeLoadResolve,
    I18nResolve,
    AppManagerService,
    AppRef,
    I18nServiceImpl,
    NavigationServiceImpl,
    SpinnerServiceImpl,
    ToasterServiceImpl,
    DynamicComponentRefProviderService,
    HttpCallInterceptor,
    PrefabManagerService,
    PipeService
} from "@wm/runtime/base";
import { AppJSProviderService } from "../framework/services/app-js-provider.service";
import { AppVariablesProviderService } from "../framework/services/app-variables-provider.service";
import { AppExtensionProviderService } from "../framework/services/app-extension.service";
import { ComponentRefProviderService } from "../framework/services/component-ref-provider.service";
import { PrefabConfigProviderService } from "../framework/services/prefab-config-provider.service";
import { CustomwidgetConfigProviderService } from "../framework/services/customwidget-config-provider.service";
import { LazyLoadScriptsResolve } from "./lazy-load-scripts.resolve";
import { 
    AbstractHttpService, 
    AbstractI18nService,
    AbstractNavigationService, 
    AbstractSpinnerService, 
    AbstractToasterService, 
    App, 
    AppDefaults, 
    CustomWidgetRefProvider, 
    DynamicComponentRefProvider,
    PartialRefProvider,
    AbstractDialogService,
    _WM_APP_PROJECT,
} from "@wm/core";
import { ModalModule } from "ngx-bootstrap/modal";
import { ToastNoAnimationModule } from "ngx-toastr";
import { BsDatepickerModule } from "ngx-bootstrap/datepicker";
import { NgCircleProgressModule } from "ng-circle-progress";
import { LocationStrategy, HashLocationStrategy, DatePipe, DecimalPipe } from "@angular/common";
import { CustomPipe, DialogServiceImpl, FilterPipe, ImagePipe, SanitizePipe, ToDatePipe, TrailingZeroDecimalPipe, TrustAsPipe } from "@wm/components/base";
import { initPrefabConfig } from "./prefabs/prefab-config";
{{#if isPwa}}
import { ServiceWorkerModule } from "@angular/service-worker";
import { environment } from "../environments/environment";
{{/if}}
{{#if isCSP}}
import { ɵSharedStylesHost } from '@angular/platform-browser';
import { ɵDomRendererFactory2 } from "@angular/platform-browser";
import { WMDomSharedStylesHost } from "@wm/runtime/base";
import { WMDomRendererFactory2 } from "@wm/runtime/base";
{{/if}}

const wmModules = [
    importProvidersFrom(
        ModalModule.forRoot(),
        ToastNoAnimationModule.forRoot({ maxOpened: 1, autoDismiss: true }),
        BsDatepickerModule.forRoot(),
        NgCircleProgressModule.forRoot(),
        {{#if isPwa}}
        ServiceWorkerModule.register("wmsw-worker.js", { enabled: environment.production })
        {{/if}}
    )
];
export const xsrfHeaderName = "{{xsrfTokenHeaderName}}";
export const isPrefabInitialized = initPrefabConfig();

const initializeProjectDetails = () => {
    let cdnUrl = document.querySelector('[name="deployUrl"]') && document.querySelector('[name="deployUrl"]').getAttribute('content');
    _WM_APP_PROJECT.isPreview = cdnUrl ? false : true;
    const apiUrl = document.querySelector('[name="apiUrl"]') && document.querySelector('[name="apiUrl"]').getAttribute('content');
    //for preview
    if (!cdnUrl) {
        cdnUrl = document.querySelector('[name="cdnUrl"]') && document.querySelector('[name="cdnUrl"]').getAttribute('content');
    }
    _WM_APP_PROJECT.id = location.href.split('/')[3];
    // Integration with third party apps like in SSPA/WebComponents, this meta tag with cdnUrl will not be there then default it to ng-bundle/
    _WM_APP_PROJECT.apiUrl = apiUrl || './';
    _WM_APP_PROJECT.cdnUrl = cdnUrl || 'ng-bundle/';
    _WM_APP_PROJECT.ngDest = 'ng-bundle/';
    try {
        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
        //@ts-ignore
        __webpack_require__.p = __webpack_public_path__ = cdnUrl;
    } catch (e) {
        //for app preview there is no webpack. Don't do anything.
    }
};

export function InitializeApp(I18nService, AppJSResolve, AppBeforeLoadResolve, AppVariablesResolve, AppExtensionJSResolve) {
    return async () => {
        initializeProjectDetails();
        await AppJSResolve.resolve();
        await AppVariablesResolve.resolve();
        await AppExtensionJSResolve.resolve();
        await I18nService.loadDefaultLocale();
        return AppBeforeLoadResolve.resolve();
    };
}

export function setAngularLocale(I18nService) {
    initializeProjectDetails();
    return I18nService.deduceAppLocale();
}

export const appConfig: ApplicationConfig = {
    providers: [
        {
            provide: HTTP_INTERCEPTORS,
            useClass: HttpCallInterceptor,
            multi: true
        },
        // Provide Angular core services
        provideRouter(routes, withHashLocation(), withComponentInputBinding()),
        provideHttpClient(
            withInterceptorsFromDi(),
            withXsrfConfiguration({
                cookieName: "wm_xsrf_token",
                headerName: xsrfHeaderName
            })
        ),
        provideAnimations(),
        // Provide application-specific services
        {
            provide: APP_INITIALIZER,
            useFactory: InitializeApp,
            deps: [AbstractI18nService, AppJSResolve, AppBeforeLoadResolve, AppVariablesResolve, AppExtensionJSResolve, PipeService],
            multi: true
        },
        {
            provide: LOCALE_ID,
            useFactory: setAngularLocale,
            deps: [AbstractI18nService]
        },
        { provide: AppJSProvider, useClass: AppJSProviderService },
        { provide: AbstractDialogService, useClass: DialogServiceImpl },
        { provide: AppVariablesProvider, useClass: AppVariablesProviderService },
        { provide: AppExtensionProvider, useClass: AppExtensionProviderService },
        { provide: ComponentRefProvider, useClass: ComponentRefProviderService },
        { provide: CustomWidgetRefProvider, useClass: ComponentRefProviderService },
        { provide: PrefabConfigProvider, useClass: PrefabConfigProviderService },
        { provide: CustomwidgetConfigProvider, useClass: CustomwidgetConfigProviderService },
        { provide: RouteReuseStrategy, useClass: WmNgRouteReuseStrategy },
        { provide: LocationStrategy, useClass: HashLocationStrategy },
        { provide: PartialRefProvider, useClass: ComponentRefProviderService },
        { provide: AbstractI18nService, useClass: I18nServiceImpl },
        { provide: AppDefaults, useClass: AppDefaultsService },
        { provide: AbstractHttpService, useClass: HttpServiceImpl },
        { provide: AbstractSpinnerService, useClass: SpinnerServiceImpl },
        { provide: App, useClass: AppRef },
        { provide: AbstractNavigationService, useClass: NavigationServiceImpl },
        { provide: AbstractToasterService, useClass: ToasterServiceImpl },
        { provide: DynamicComponentRefProvider, useClass: DynamicComponentRefProviderService, },
        {{#if isCSP}}
        { provide: ɵSharedStylesHost, useClass: WMDomSharedStylesHost },
        { provide: ɵDomRendererFactory2, useClass: WMDomRendererFactory2 },
        {{/if}}
        PageDirective,
        AppManagerService,
        DatePipe,
        {{#if enableSpa}}SpaPageDirective,{{/if}}
        AppJSResolve,
        AppExtensionJSResolve,
        AppVariablesResolve,
        AppBeforeLoadResolve,
        PipeService,
        I18nResolve,
        SecurityService,
        OAuthService,
        VariablesService,
        MetadataService,
        PrefabManagerService,
        SanitizePipe,
        ToDatePipe,
        FilterPipe,
        TrailingZeroDecimalPipe,
        TrustAsPipe,
        DecimalPipe,
        ImagePipe,
        CustomPipe,
        Location,
        // Other application-wide services
        CanDeactivateNgPageGuard,
        LazyLoadScriptsResolve,
        {{#if enableSecurity}}AuthGuard, RoleGuard, {{/if}}
        ...wmModules
    ]
};
