import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

import { NgModule } from '@angular/core';

import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import { StoreRouterConnectingModule, RouterState } from '@ngrx/router-store';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';

import { LoggerModule } from '@ucap/ng-logger';

import { CommonApiModule } from '@ucap/ng-api-common';
import { PublicApiModule } from '@ucap/ng-api-public';
import { ExternalApiModule } from '@ucap/ng-api-external';
import { MessageApiModule } from '@ucap/ng-api-message';
import { PromptApiModule } from '@ucap/ng-api-prompt';

import { PiModule } from '@ucap/ng-pi';

import { ProtocolModule } from '@ucap/ng-protocol';
import { AuthenticationProtocolModule } from '@ucap/ng-protocol-authentication';
import { BuddyProtocolModule } from '@ucap/ng-protocol-buddy';
import { EventProtocolModule } from '@ucap/ng-protocol-event';
import { FileProtocolModule } from '@ucap/ng-protocol-file';
import { GroupProtocolModule } from '@ucap/ng-protocol-group';
import { InfoProtocolModule } from '@ucap/ng-protocol-info';
import { InnerProtocolModule } from '@ucap/ng-protocol-inner';
import { OptionProtocolModule } from '@ucap/ng-protocol-option';
import { PingProtocolModule } from '@ucap/ng-protocol-ping';
import { QueryProtocolModule } from '@ucap/ng-protocol-query';
import { RoomProtocolModule } from '@ucap/ng-protocol-room';
import { ServiceProtocolModule } from '@ucap/ng-protocol-service';
import { StatusProtocolModule } from '@ucap/ng-protocol-status';
import { SyncProtocolModule } from '@ucap/ng-protocol-sync';
import { UmgProtocolModule } from '@ucap/ng-protocol-umg';

import { WebSocketModule } from '@ucap/ng-web-socket';
import { WebStorageModule } from '@ucap/ng-web-storage';

import { I18nModule } from '@ucap/ng-i18n';

import { OrganizationStoreModule } from '@ucap/ng-store-organization';
import { AuthenticationStoreModule } from '@ucap/ng-store-authentication';
import { GroupStoreModule } from '@ucap/ng-store-group';
import { ChatStoreModule } from '@ucap/ng-store-chat';

import { OrganizationUiModule } from '@ucap/ng-ui-organization';

import { AppLayoutsModule } from '@app/layouts/layouts.module';

import { AppProviderModule } from '@app/app-provider.module';
import { AppRoutingModule } from '@app/app-routing.module';
import { AppComponent } from '@app/app.component';

import { effects } from '@app/store/effects';
import { ROOT_REDUCERS } from '@app/store/reducers';
import { metaReducers } from '@app/store/state';

import { environment } from '@environments';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,

    LoggerModule.forRoot({}),

    CommonApiModule.forRoot(environment.commonApiModuleConfig),
    PublicApiModule.forRoot(environment.publicApiModuleConfig),
    ExternalApiModule.forRoot(environment.externalApiModuleConfig),
    MessageApiModule.forRoot(environment.messageApiModuleConfig),
    PromptApiModule.forRoot(environment.promptApiModuleConfig),

    PiModule.forRoot(environment.piModuleConfig),

    ProtocolModule.forRoot(environment.protocolModuleConfig),
    AuthenticationProtocolModule.forRoot({}),
    BuddyProtocolModule.forRoot({}),
    EventProtocolModule.forRoot({}),
    FileProtocolModule.forRoot({}),
    GroupProtocolModule.forRoot({}),
    InfoProtocolModule.forRoot({}),
    InnerProtocolModule.forRoot({}),
    OptionProtocolModule.forRoot({}),
    PingProtocolModule.forRoot(environment.pingProtocolModuleConfig),
    QueryProtocolModule.forRoot({}),
    RoomProtocolModule.forRoot({}),
    ServiceProtocolModule.forRoot({}),
    StatusProtocolModule.forRoot({}),
    SyncProtocolModule.forRoot({}),
    UmgProtocolModule.forRoot({}),

    WebSocketModule.forRoot(environment.webSocketModuleConfig),
    WebStorageModule.forRoot({}),

    I18nModule.forRoot({}),

    OrganizationStoreModule.forRoot({}),
    AuthenticationStoreModule.forRoot({}),
    GroupStoreModule.forRoot({ useMyDeptGroup: true, fixedGroupSeqs: [] }),
    ChatStoreModule.forRoot({}),

    OrganizationUiModule.forRoot({}),

    AppProviderModule,
    AppRoutingModule,

    AppLayoutsModule,

    /**
     * StoreModule.forRoot is imported once in the root module, accepting a reducer
     * function or object map of reducer functions. If passed an object of
     * reducers, combineReducers will be run creating your application
     * meta-reducer. This returns all providers for an @ngrx/store
     * based application.
     */
    StoreModule.forRoot(ROOT_REDUCERS, {
      metaReducers,
      runtimeChecks: {
        strictStateImmutability: true,
        strictActionImmutability: true,
        strictStateSerializability: true,
        strictActionSerializability: true
      }
    }),

    /**
     * @ngrx/router-store keeps router state up-to-date in the store.
     */
    StoreRouterConnectingModule.forRoot({
      routerState: RouterState.Minimal
    }),

    /**
     * Store devtools instrument the store retaining past versions of state
     * and recalculating new states. This enables powerful time-travel
     * debugging.
     *
     * To use the debugger, install the Redux Devtools extension for either
     * Chrome or Firefox
     *
     * See: https://github.com/zalmoxisus/redux-devtools-extension
     */
    StoreDevtoolsModule.instrument({
      name: 'UCAP Store App'

      // In a production build you would want to disable the Store Devtools
      // logOnly: environment.production,
    }),

    /**
     * EffectsModule.forRoot() is imported once in the root module and
     * sets up the effects class to be initialized immediately when the
     * application starts.
     *
     * See: https://ngrx.io/guide/effects#registering-root-effects
     */
    EffectsModule.forRoot([...effects])
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {}
