import { BrowserModule, HammerModule } from "@angular/platform-browser";
import { APP_INITIALIZER, LOCALE_ID, NgModule } from "@angular/core";

import { TranslateModule, TranslateLoader, TranslateService } from "@ngx-translate/core";
import { HttpClientModule, HttpClient } from "@angular/common/http";
import { TranslateHttpLoader } from "@ngx-translate/http-loader";

import { FormsModule } from "@angular/forms";
import { AppRoutingModule } from "./app-routing.module";

import { MaterialModule } from "./material.module";
import { LazyLoadImageModule } from "ng-lazyload-image";

import { ServerRestApiService } from "./shared/services/server-rest-api.service";

import { CookieModule } from "ngx-cookie";

import { LocalStorageService } from "./shared/services/local-storage.service";
import { AuthService } from "./shared/server-services/auth.service";
import { RouterHandler } from "./shared/services/router-handler.service";
// custom components
import { AppComponent } from "./app.component";
import { WelcomeComponent } from "./components/welcome/welcome.component";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { ReactiveFormsModule } from "@angular/forms";

import { ResourcesSidebarComponent } from "./components/resources-sidebar/resources-sidebar.component";
import { ResourceGroupComponent } from "./components/resources-sidebar/resource-group/resource-group.component";
import { ResourceNodeComponent } from "./components/resources-sidebar/resource-node/resource-node.component";
import { NewGroupDialogComponent } from "./shared/dialogs/new-group-dialog/new-group-dialog.component";
import { RenameGroupDialogComponent } from "./shared/dialogs/rename-group-dialog/rename-group-dialog.component";
import { DeleteGroupDialogComponent } from "./shared/dialogs/delete-group-dialog/delete-group-dialog.component";
import { DeleteFileDialogComponent } from "./shared/dialogs/delete-file-dialog/delete-file-dialog.component";
import { NewFolderDialogComponent } from "./shared/dialogs/new-folder-dialog/new-folder-dialog.component";
import { MarkdownViewComponent } from "./components/resource-page/chat-layout/chat-message/markdown-view/markdown-view.component";

import { AppDragDropModule } from "./shared/drag/app-drag-drop-module";
import { AppGuideModule } from "./shared/guide/app-guide-module";
import { MarkdownEditorComponent } from "./components/resource-page/chat-layout/chat-message/markdown-editor/markdown-editor.component";
import { EmojiPickerComponent } from "./components/resource-page/chat-layout/chat-message/markdown-editor/emoji-picker/emoji-picker.component";
import { EmojiShortcodePickerComponent } from "./components/resource-page/chat-layout/chat-message/markdown-editor/emoji-shortcode-picker/emoji-shortcode-picker.component";
import { LoginComponent } from "./components/login/login.component";
import { RegisterComponent } from "./components/register/register.component";
import { ChatLayoutComponent } from "./components/resource-page/chat-layout/chat-layout.component";
import { ChatMessageComponent } from "./components/resource-page/chat-layout/chat-message/chat-message.component";
import { DriveLayoutComponent } from "./components/resource-page/drive-window/drive-layout/drive-layout.component";
import { ResourcePageComponent } from "./components/resource-page/resource-page.component";
import { SettingsComponent } from "./components/settings/settings.component";
import { HeaderComponent } from "./components/header/header.component";
import { AvatarComponent } from "./shared/components/avatar/avatar.component";
import { FileBlockViewComponent } from "./components/resource-page/drive-window/drive-layout/file-block-view/file-block-view.component";

import { SortByPipe } from "./components/resources-sidebar/orderby.pipe";
import { SidebarElementDragPreviewComponent } from "./components/resources-sidebar/sidebar-element-drag-preview/sidebar-element-drag-preview.component";
import { DoubleClickDirective } from "./shared/directives/double-click.directive";
import { FileListViewComponent } from "./components/resource-page/drive-window/drive-layout/file-list-view/file-list-view.component";
import { DriveWindowComponent } from "./components/resource-page/drive-window/drive-window.component";
import { SearchInputComponent } from "./components/header/search-input/search-input.component";
import { SearchViewComponent } from "./components/search-view/search-view.component";
import { SearchViewResultComponent } from "./components/search-view/search-view-result/search-view-result.component";
import { PathToArrayPipe } from "./shared/pipes/path-to-array.pipe";
import { HighlightWordPipe } from "./shared/pipes/highlight-word.pipe";
import { SafePipe } from "./shared/pipes/safe-pipe";
import { SearchSidebarViewComponent } from "./components/resources-sidebar/search-sidebar-view/search-sidebar-view.component";
import { ActivatedRoute, DefaultUrlSerializer, Router, UrlSerializer, UrlTree } from "@angular/router";
import { DownloadManagerComponent } from "./components/download-manager/download-manager.component";
import { DownloadManagerFileComponent } from "./components/download-manager/download-manager-file/download-manager-file.component";
import { ActionQueueComponent } from "./components/action-queue/action-queue.component";
import { ActionQueueElementComponent } from "./components/action-queue/action-queue-element/action-queue-element.component";
import { SubscriptionService } from "./shared/server-services/subscription.service";
import { NanoLicenseComponent } from './components/nano-license/nano-license.component';
import { RoomDetailsComponent } from './/components/resource-page/room-details/room-details.component';
import { InviteUserDialogComponent } from './shared/dialogs/invite-user-dialog/invite-user-dialog.component';
import {TranslatePoHttpLoader} from './shared/translatePoHttpLoader';
import { CurrencyPipe, registerLocaleData } from "@angular/common";
import localeHu from '@angular/common/locales/hu';
import { NanoManagerComponent } from './components/nano-manager/nano-manager.component';
import { AttachRoomDialogComponent } from './components/nano-manager/attach-room-dialog/attach-room-dialog.component';
import { CreateDriveDialogComponent } from './components/nano-manager/create-drive-dialog/create-drive-dialog.component';
import { GeneralAlertDialogComponent } from './shared/dialogs/general-alert-dialog/general-alert-dialog.component';
import { DialogService } from './shared/services/dialog.service';
import { TitleService } from './shared/services/title.service';
import { AudioService } from './shared/services/audio.service';
import { VersionService } from './shared/services/version.service';
import { AdminPasswordDialogComponent } from './components/nano-manager/admin-password-dialog/admin-password-dialog.component';
import { GeneralConfirmDialogComponent } from './shared/dialogs/general-confirm-dialog/general-confirm-dialog.component';
import { CreateRoomDialogComponent } from './shared/dialogs/create-room-dialog/create-room-dialog.component';
import { AccountSettingsComponent } from './components/account-settings/account-settings.component';
import { TwoFactorDialogComponent } from './shared/dialogs/two-factor-dialog/two-factor-dialog.component';
import { ChangeUsernameDialogComponent } from './components/account-settings/change-username-dialog/change-username-dialog.component';
import { ChangePasswordDialogComponent } from './components/account-settings/change-password-dialog/change-password-dialog.component';
import { ChangeEmailDialogComponent } from './components/account-settings/change-email-dialog/change-email-dialog.component';
import { ImageCropperDialogComponent } from './shared/dialogs/image-cropper-dialog/image-cropper-dialog.component';
import { environment } from '../environments/environment';
import { EnvironmentService } from '../environments/environment.service';
import { RegisterConfirmComponent } from './components/register-confirm/register-confirm.component';
import { ZxcvbnDirective } from './shared/directives/zxcvbn.directive';
import { AboutComponent } from './components/about/about.component';
import { HidePipe } from './shared/pipes/hide.pipe';
import { EnterTheViewportNotifierDirective } from './shared/directives/enter-the-viewport-notifier.directive';
import { ContactListComponent } from './components/contact-list/contact-list.component';
import { UserInfoMenuComponent } from './shared/components/user-info-menu/user-info-menu.component';
import { ShowUserInfoDirective } from './shared/directives/show-user-info.directive';
import { MAT_DIALOG_DEFAULT_OPTIONS } from "@angular/material/dialog";
import { TimedOffersComponent } from './components/timed-offers/timed-offers.component';
import { AccountRecoveryComponent } from './components/account-recovery/account-recovery.component';
import { AccountRecoveryConfirmComponent } from './components/account-recovery-confirm/account-recovery-confirm.component';
import { GeneralInputDialogComponent } from './shared/dialogs/general-input-dialog/general-input-dialog.component';
import { DownloadRecoveryCodeDialogComponent } from './shared/dialogs/download-recovery-code-dialog/download-recovery-code-dialog.component';
import { AdvancedSettingsComponent } from './components/advanced-settings/advanced-settings.component';
import { WorkerGraphComponent } from './components/worker-graph/worker-graph.component';
import { BundledLicensesDialogComponent } from './components/nano-license/bundled-licenses-dialog/bundled-licenses-dialog.component';
import { RedeemTokenDialogComponent } from './components/nano-license/redeem-token-dialog/redeem-token-dialog.component';
import { BlobViewerComponent } from './components/blob-viewer/blob-viewer.component';
import { ContextMenuDirective } from './shared/directives/context-menu.directive';
import { ContactDialogComponent } from './shared/dialogs/contact-dialog/contact-dialog.component';
import { MarkdownFilePreviewComponent } from './components/resource-page/chat-layout/chat-message/markdown-view/markdown-file-preview/markdown-file-preview.component';
import { SessionHandlerComponent } from './components/session-handler/session-handler.component';
import { SaleCodeManagerComponent } from './components/sale-code-manager/sale-code-manager.component';
import { CreateEditSaleCodeDialogComponent } from './components/sale-code-manager/create-edit-sale-code-dialog/create-edit-sale-code-dialog.component';
import { EditBillingTemplateDialogComponent } from "./components/nano-license-buy/edit-billing-template-dialog/edit-billing-template-dialog.component";
import { NanoLicenseBuyComponent } from "./components/nano-license-buy/nano-license-buy.component";
import { RecurringOrderDetailDialogComponent } from "./components/nano-license/recurring-order-detail-dialog/recurring-order-detail-dialog.component";
import { SimplepayBackComponent } from "./components/simplepay-back/simplepay-back.component";
import { AggregateStatsComponent } from './components/aggregate-stats/aggregate-stats.component';
import { FormatBytesPipe } from './shared/pipes/format-bytes.pipe';
import { OutboundLinkDialogComponent } from './shared/dialogs/outbound-link-dialog/outbound-link-dialog.component';
import { CordovaService } from "./shared/services/cordova.service";
import { CopyChatMessagesSnackbarComponent } from './shared/snackbars/copy-chat-messages-snackbar/copy-chat-messages-snackbar.component';

//angular needs locale data for built-in translations for resources like for example date formats
registerLocaleData(localeHu);

// AoT requires an exported function for factories
export function HttpLoaderFactory(http: HttpClient): TranslatePoHttpLoader {
  return new TranslatePoHttpLoader(http, './assets/i18n', '.po');
}

export class DynamicLocaleId extends String {
  constructor(protected service: TranslateService) {
    super('');
  }

  toString() {
    return this.service.currentLang;
  }
}

class CustomUrlSerializer implements UrlSerializer {

  private defaultUrlSerializer = new DefaultUrlSerializer();

  parse(url: string): UrlTree {
    return this.defaultUrlSerializer.parse(url)  
  }

  serialize(tree: UrlTree): string {
    let serialized = this.defaultUrlSerializer.serialize(tree);
    let parts = serialized.split('#');
    if (parts.length > 1){
      serialized = parts[0]+"#"+tree.fragment;
    }
    return serialized;
  }
}

@NgModule({
  declarations: [
    AppComponent,
    WelcomeComponent,
    ResourcesSidebarComponent,
    ResourceGroupComponent,
    ResourceNodeComponent,
    NewGroupDialogComponent,
    RenameGroupDialogComponent,
    DeleteGroupDialogComponent,
    DeleteFileDialogComponent,
    NewFolderDialogComponent,
    MarkdownViewComponent,
    MarkdownEditorComponent,
    EmojiPickerComponent,
    EmojiShortcodePickerComponent,
    LoginComponent,
    RegisterComponent,
    ChatLayoutComponent,
    ChatMessageComponent,
    DriveLayoutComponent,
    ResourcePageComponent,
    SettingsComponent,
    HeaderComponent,
    AvatarComponent,
    FileBlockViewComponent,
    SortByPipe,
    SidebarElementDragPreviewComponent,
    DoubleClickDirective,
    FileListViewComponent,
    DriveWindowComponent,
    SearchInputComponent,
    SearchViewComponent,
    SearchViewResultComponent,
    PathToArrayPipe,
    HighlightWordPipe,
    SafePipe,
    SearchSidebarViewComponent,
    DownloadManagerComponent,
    DownloadManagerFileComponent,
    ActionQueueComponent,
    ActionQueueElementComponent,
    NanoLicenseComponent,
    RoomDetailsComponent,
    InviteUserDialogComponent,
    NanoManagerComponent,
    AttachRoomDialogComponent,
    CreateDriveDialogComponent,
    GeneralAlertDialogComponent,
    AdminPasswordDialogComponent,
    GeneralConfirmDialogComponent,
    CreateRoomDialogComponent,
    AccountSettingsComponent,
    TwoFactorDialogComponent,
    ChangeUsernameDialogComponent,
    ImageCropperDialogComponent,
    ChangePasswordDialogComponent,
    ChangeEmailDialogComponent,
    RegisterConfirmComponent,
    ZxcvbnDirective,
    AboutComponent,
    HidePipe,
    EnterTheViewportNotifierDirective,
    ContactListComponent,
    UserInfoMenuComponent,
    ShowUserInfoDirective,
    TimedOffersComponent,
    AccountRecoveryComponent,
    AccountRecoveryConfirmComponent,
    GeneralInputDialogComponent,
    DownloadRecoveryCodeDialogComponent,
    AdvancedSettingsComponent,
    WorkerGraphComponent,
    BlobViewerComponent,
    ContextMenuDirective,
    ContactDialogComponent,
    MarkdownFilePreviewComponent,
    SessionHandlerComponent,
    BundledLicensesDialogComponent,
    RedeemTokenDialogComponent,
    BlobViewerComponent,
    SaleCodeManagerComponent,
    CreateEditSaleCodeDialogComponent,
    NanoLicenseBuyComponent,
    EditBillingTemplateDialogComponent,
    SimplepayBackComponent,
    BlobViewerComponent,
    ContextMenuDirective,
    ContactDialogComponent,
    MarkdownFilePreviewComponent,
    SessionHandlerComponent,
    RecurringOrderDetailDialogComponent,
    CreateEditSaleCodeDialogComponent,
    AggregateStatsComponent,
    FormatBytesPipe,
    OutboundLinkDialogComponent,
    CopyChatMessagesSnackbarComponent
  ],
  imports: [
    BrowserModule,
    HammerModule,
    AppRoutingModule,
    HttpClientModule,
    ReactiveFormsModule,
    AppDragDropModule,
    AppGuideModule,
    TranslateModule.forRoot({
      defaultLanguage: 'en',
      loader: {
        provide: TranslateLoader,
        useFactory: HttpLoaderFactory,
        deps: [HttpClient]
      }
    }),
    BrowserAnimationsModule,
    FormsModule,
    MaterialModule,
    LazyLoadImageModule,
    CookieModule.forRoot()
  ],
  providers: [
    { provide: UrlSerializer, useClass: CustomUrlSerializer },
    ServerRestApiService,
    LocalStorageService,
    DialogService,
    TitleService,
    AudioService,
    AuthService,
    SubscriptionService,
    VersionService,
    FormatBytesPipe,
    CurrencyPipe,
    CordovaService,
    {
      provide: RouterHandler,
      useClass: RouterHandler,
      deps: [Router],
    },
    { provide: LOCALE_ID, useClass: DynamicLocaleId, deps: [TranslateService] },
    { provide: EnvironmentService, useValue: environment},
    { provide: MAT_DIALOG_DEFAULT_OPTIONS, useValue: {disableClose: true, hasBackdrop: true, autoFocus: 'first-tabbable'}}
  ],
  bootstrap: [AppComponent],
})
export class AppModule {
  constructor() { }
}