import { HttpErrorResponse } from '@angular/common/http';
import { Injector } from '@angular/core';
import { Event, NavigationError, Router } from '@angular/router';
import { NgCortexService } from '@ng-cortex/core';
import { NzNotificationService } from 'ng-zorro-antd/notification';
import { filter, map, tap } from 'rxjs/operators';
import { environment } from '../../../../environments/environment';

import * as NgAnimationsLibrary from '@angular/animations';
import * as NgCdkDragDropLibrary from '@angular/cdk/drag-drop';
import * as NgCommonLibrary from '@angular/common';
import * as NgCommonHttpLibrary from '@angular/common/http';
import * as NgCompilerLibrary from '@angular/compiler';
import * as NgCoreLibrary from '@angular/core';
import * as NgFormsLibrary from '@angular/forms';
import * as NgPlatformBrowserLibrary from '@angular/platform-browser';
import * as NgRouterLibrary from '@angular/router';
import * as DateFnsLibrary from 'date-fns';
import * as RxJSLibrary from 'rxjs';
import * as RxJSOperatorsLibrary from 'rxjs/operators';
import * as NzAffixLibrary from 'ng-zorro-antd/affix';
import * as NzAlertLibrary from 'ng-zorro-antd/alert';
import * as NzAnchorLibrary from 'ng-zorro-antd/anchor';
import * as NzAutocompleteLibrary from 'ng-zorro-antd/auto-complete';
import * as NzAvatarLibrary from 'ng-zorro-antd/avatar';
import * as NzBackTopLibrary from 'ng-zorro-antd/back-top';
import * as NzBadgeLibrary from 'ng-zorro-antd/badge';
import * as NzBreadCrumbLibrary from 'ng-zorro-antd/breadcrumb';
import * as NzButtonLibrary from 'ng-zorro-antd/button';
import * as NzCalendarLibrary from 'ng-zorro-antd/calendar';
import * as NzCardLibrary from 'ng-zorro-antd/card';
import * as NzCarouselLibrary from 'ng-zorro-antd/carousel';
import * as NzCascaderLibrary from 'ng-zorro-antd/cascader';
import * as NzCheckboxLibrary from 'ng-zorro-antd/checkbox';
import * as NzCollapseLibrary from 'ng-zorro-antd/collapse';
import * as NzCommentLibrary from 'ng-zorro-antd/comment';
import * as NzNoAnimationLibrary from 'ng-zorro-antd/core/no-animation';
import * as NzTransButtonLibrary from 'ng-zorro-antd/core/trans-button';
import * as NzTransitionPatchLibrary from 'ng-zorro-antd/core/transition-patch';
import * as NzWaveLibrary from 'ng-zorro-antd/core/wave';
import * as NzDatePickerLibrary from 'ng-zorro-antd/date-picker';
import * as NzDescriptionsLibrary from 'ng-zorro-antd/descriptions';
import * as NzDividerLibrary from 'ng-zorro-antd/divider';
import * as NzDrawerLibrary from 'ng-zorro-antd/drawer';
import * as NzDropDownLibrary from 'ng-zorro-antd/dropdown';
import * as NzEmptyLibrary from 'ng-zorro-antd/empty';
import * as NzFormLibrary from 'ng-zorro-antd/form';
import * as NzGridLibrary from 'ng-zorro-antd/grid';
import * as NzI18nLibrary from 'ng-zorro-antd/i18n';
import * as NzIconLibrary from 'ng-zorro-antd/icon';
import * as NzImageLibrary from 'ng-zorro-antd/image';
import * as NzInputLibrary from 'ng-zorro-antd/input';
import * as NzInputNumberLibrary from 'ng-zorro-antd/input-number';
import * as NzLayoutLibrary from 'ng-zorro-antd/layout';
import * as NzListLibrary from 'ng-zorro-antd/list';
import * as NzMentionLibrary from 'ng-zorro-antd/mention';
import * as NzMenuLibrary from 'ng-zorro-antd/menu';
import * as NzMessageLibrary from 'ng-zorro-antd/message';
import * as NzModalLibrary from 'ng-zorro-antd/modal';
import * as NzNotificationLibrary from 'ng-zorro-antd/notification';
import * as NzPageHeaderLibrary from 'ng-zorro-antd/page-header';
import * as NzPaginationLibrary from 'ng-zorro-antd/pagination';
import * as NzPopconfirmLibrary from 'ng-zorro-antd/popconfirm';
import * as NzPopoverLibrary from 'ng-zorro-antd/popover';
import * as NzProgressLibrary from 'ng-zorro-antd/progress';
import * as NzRadioLibrary from 'ng-zorro-antd/radio';
import * as NzRateLibrary from 'ng-zorro-antd/rate';
import * as NzResultLibrary from 'ng-zorro-antd/result';
import * as NzSelectLibrary from 'ng-zorro-antd/select';
import * as NzSkeletonLibrary from 'ng-zorro-antd/skeleton';
import * as NzSliderLibrary from 'ng-zorro-antd/slider';
import * as NzSpinLibrary from 'ng-zorro-antd/spin';
import * as NzStatisticLibrary from 'ng-zorro-antd/statistic';
import * as NzStepsLibrary from 'ng-zorro-antd/steps';
import * as NzSwitchLibrary from 'ng-zorro-antd/switch';
import * as NzTableLibrary from 'ng-zorro-antd/table';
import * as NzTabsLibrary from 'ng-zorro-antd/tabs';
import * as NzTagLibrary from 'ng-zorro-antd/tag';
import * as NzTimePickerLibrary from 'ng-zorro-antd/time-picker';
import * as NzTimelineLibrary from 'ng-zorro-antd/timeline';
import * as NzToolTipLibrary from 'ng-zorro-antd/tooltip';
import * as NzTransferLibrary from 'ng-zorro-antd/transfer';
import * as NzTreeLibrary from 'ng-zorro-antd/tree';
import * as NzTreeViewLibrary from 'ng-zorro-antd/tree-view';
import * as NzTreeSelectLibrary from 'ng-zorro-antd/tree-select';
import * as NzTypographyLibrary from 'ng-zorro-antd/typography';
import * as NzUploadLibrary from 'ng-zorro-antd/upload';
import * as NzResizableLibrary from 'ng-zorro-antd/resizable';
import * as NzPipesLibrary from 'ng-zorro-antd/pipes';
import * as NgCortexCoreLibrary from '@ng-cortex/core';
import * as NgCortexUtilsLibrary from '@ng-cortex/utils';

/** 程序启动制造器 */
export function AppStartupFactory(injector: Injector): () => Promise<void> {
    const router = injector.get(Router);
    const nzNotificationService = injector.get(NzNotificationService);
    const ngCortexService = injector.get(NgCortexService);
    return () => ngCortexService
        .registerDependency('@angular/animations', NgAnimationsLibrary)
        .registerDependency('@angular/cdk/drag-drop', NgCdkDragDropLibrary)
        .registerDependency('@angular/common', NgCommonLibrary)
        .registerDependency('@angular/common/http', NgCommonHttpLibrary)
        .registerDependency('@angular/compiler', NgCompilerLibrary)
        .registerDependency('@angular/core', NgCoreLibrary)
        .registerDependency('@angular/forms', NgFormsLibrary)
        .registerDependency('@angular/platform-browser', NgPlatformBrowserLibrary)
        .registerDependency('@angular/router', NgRouterLibrary)
        .registerDependency('date-fns', DateFnsLibrary)
        .registerDependency('rxjs', RxJSLibrary)
        .registerDependency('rxjs/operators', RxJSOperatorsLibrary)
        .registerDependency('ng-zorro-antd/affix', NzAffixLibrary)
        .registerDependency('ng-zorro-antd/alert', NzAlertLibrary)
        .registerDependency('ng-zorro-antd/anchor', NzAnchorLibrary)
        .registerDependency('ng-zorro-antd/auto-complete', NzAutocompleteLibrary)
        .registerDependency('ng-zorro-antd/avatar', NzAvatarLibrary)
        .registerDependency('ng-zorro-antd/back-top', NzBackTopLibrary)
        .registerDependency('ng-zorro-antd/badge', NzBadgeLibrary)
        .registerDependency('ng-zorro-antd/breadcrumb', NzBreadCrumbLibrary)
        .registerDependency('ng-zorro-antd/button', NzButtonLibrary)
        .registerDependency('ng-zorro-antd/calendar', NzCalendarLibrary)
        .registerDependency('ng-zorro-antd/card', NzCardLibrary)
        .registerDependency('ng-zorro-antd/carousel', NzCarouselLibrary)
        .registerDependency('ng-zorro-antd/cascader', NzCascaderLibrary)
        .registerDependency('ng-zorro-antd/checkbox', NzCheckboxLibrary)
        .registerDependency('ng-zorro-antd/collapse', NzCollapseLibrary)
        .registerDependency('ng-zorro-antd/comment', NzCommentLibrary)
        .registerDependency('ng-zorro-antd/core/no-animation', NzNoAnimationLibrary)
        .registerDependency('ng-zorro-antd/core/trans-button', NzTransButtonLibrary)
        .registerDependency('ng-zorro-antd/core/transition-patch', NzTransitionPatchLibrary)
        .registerDependency('ng-zorro-antd/core/wave', NzWaveLibrary)
        .registerDependency('ng-zorro-antd/date-picker', NzDatePickerLibrary)
        .registerDependency('ng-zorro-antd/descriptions', NzDescriptionsLibrary)
        .registerDependency('ng-zorro-antd/divider', NzDividerLibrary)
        .registerDependency('ng-zorro-antd/drawer', NzDrawerLibrary)
        .registerDependency('ng-zorro-antd/dropdown', NzDropDownLibrary)
        .registerDependency('ng-zorro-antd/empty', NzEmptyLibrary)
        .registerDependency('ng-zorro-antd/form', NzFormLibrary)
        .registerDependency('ng-zorro-antd/grid', NzGridLibrary)
        .registerDependency('ng-zorro-antd/i18n', NzI18nLibrary)
        .registerDependency('ng-zorro-antd/icon', NzIconLibrary)
        .registerDependency('ng-zorro-antd/image', NzImageLibrary)
        .registerDependency('ng-zorro-antd/input', NzInputLibrary)
        .registerDependency('ng-zorro-antd/input-number', NzInputNumberLibrary)
        .registerDependency('ng-zorro-antd/layout', NzLayoutLibrary)
        .registerDependency('ng-zorro-antd/list', NzListLibrary)
        .registerDependency('ng-zorro-antd/mention', NzMentionLibrary)
        .registerDependency('ng-zorro-antd/menu', NzMenuLibrary)
        .registerDependency('ng-zorro-antd/message', NzMessageLibrary)
        .registerDependency('ng-zorro-antd/modal', NzModalLibrary)
        .registerDependency('ng-zorro-antd/notification', NzNotificationLibrary)
        .registerDependency('ng-zorro-antd/page-header', NzPageHeaderLibrary)
        .registerDependency('ng-zorro-antd/pagination', NzPaginationLibrary)
        .registerDependency('ng-zorro-antd/popconfirm', NzPopconfirmLibrary)
        .registerDependency('ng-zorro-antd/popover', NzPopoverLibrary)
        .registerDependency('ng-zorro-antd/progress', NzProgressLibrary)
        .registerDependency('ng-zorro-antd/radio', NzRadioLibrary)
        .registerDependency('ng-zorro-antd/rate', NzRateLibrary)
        .registerDependency('ng-zorro-antd/result', NzResultLibrary)
        .registerDependency('ng-zorro-antd/select', NzSelectLibrary)
        .registerDependency('ng-zorro-antd/skeleton', NzSkeletonLibrary)
        .registerDependency('ng-zorro-antd/slider', NzSliderLibrary)
        .registerDependency('ng-zorro-antd/spin', NzSpinLibrary)
        .registerDependency('ng-zorro-antd/statistic', NzStatisticLibrary)
        .registerDependency('ng-zorro-antd/steps', NzStepsLibrary)
        .registerDependency('ng-zorro-antd/switch', NzSwitchLibrary)
        .registerDependency('ng-zorro-antd/table', NzTableLibrary)
        .registerDependency('ng-zorro-antd/tabs', NzTabsLibrary)
        .registerDependency('ng-zorro-antd/tag', NzTagLibrary)
        .registerDependency('ng-zorro-antd/time-picker', NzTimePickerLibrary)
        .registerDependency('ng-zorro-antd/timeline', NzTimelineLibrary)
        .registerDependency('ng-zorro-antd/tooltip', NzToolTipLibrary)
        .registerDependency('ng-zorro-antd/transfer', NzTransferLibrary)
        .registerDependency('ng-zorro-antd/tree', NzTreeLibrary)
        .registerDependency('ng-zorro-antd/tree-view', NzTreeViewLibrary)
        .registerDependency('ng-zorro-antd/tree-select', NzTreeSelectLibrary)
        .registerDependency('ng-zorro-antd/typography', NzTypographyLibrary)
        .registerDependency('ng-zorro-antd/upload', NzUploadLibrary)
        .registerDependency('ng-zorro-antd/resizable', NzResizableLibrary)
        .registerDependency('ng-zorro-antd/pipes', NzPipesLibrary)
        .registerDependency('@ng-cortex/core', NgCortexCoreLibrary)
        .registerDependency('@ng-cortex/utils', NgCortexUtilsLibrary)
        .initialize({
            resconfigUrl: environment.resconfigUrl,
            coreService: environment.coreService,
            titleSuffix: environment.titleSuffix,
            storageKeyForToken: environment.storageKeyForToken,
            routeForLogin: '/login',
            routeForApplicationIndex: '/apps',
            routeForApplication403: '/apps/403',
            routeForApplication404: '/apps/404',
            routeForApplication500: '/apps/500',
            routeReuse: environment.routeReuse
        })
        .pipe(map(() => {
            (window as any).Spinner.done();
            router.events
                .pipe(filter<Event, NavigationError>((event): event is NavigationError => event instanceof NavigationError))
                .subscribe(navigationError => {
                    nzNotificationService.error('加载页面失败', navigationError.error && navigationError.error.message || navigationError.toString());
                });
        }))
        .pipe(tap(() => { }, (httpErrorResponse: HttpErrorResponse) => {
            (window as any).Spinner.done();
            nzNotificationService.error('初始化失败', httpErrorResponse.error && httpErrorResponse.error.message || httpErrorResponse.statusText);
            const errorContainer = document.createElement('div');
            errorContainer.innerHTML = '<div style="position: absolute; top: 0px; left: 0px; min-width: 100%; min-height: 100%; display: flex; flex-direction: column; justify-content: center; align-items: center;">' +
                '<img src="/assets/images/init-fail.svg" style="height: 300px; margin-bottom: 24px;">' +
                '<span class="ant-result-title">初始化失败</span>' +
                '</div>';
            document.body.appendChild(errorContainer.firstElementChild!);
        }))
        .toPromise();
}
