import { Component, OnInit, ElementRef, ViewChild, HostBinding, AfterViewInit } from '@angular/core';
import {MatDialogRef} from '@angular/material/dialog';
import {PostsService} from './posts.services';
import { MatDialog } from '@angular/material/dialog';
import { MatSidenav } from '@angular/material/sidenav';
import { MatSnackBar } from '@angular/material/snack-bar';
import { saveAs } from 'file-saver';
import { Router, NavigationStart, NavigationEnd } from '@angular/router';
import { OverlayContainer } from '@angular/cdk/overlay';
import { THEMES_CONFIG } from '../themes';
import { SettingsComponent } from './settings/settings.component';
import { AboutDialogComponent } from './dialogs/about-dialog/about-dialog.component';
import { UserProfileDialogComponent } from './dialogs/user-profile-dialog/user-profile-dialog.component';
import { SetDefaultAdminDialogComponent } from './dialogs/set-default-admin-dialog/set-default-admin-dialog.component';
import { NotificationsComponent } from './components/notifications/notifications.component';
import { ArchiveViewerComponent } from './components/archive-viewer/archive-viewer.component';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css'],
    providers: [{
            provide: MatDialogRef,
            useValue: {}
        }],
    standalone: false
})
export class AppComponent implements OnInit, AfterViewInit {

  @HostBinding('class') componentCssClass;
  THEMES_CONFIG = THEMES_CONFIG;

  window = window;

  // config items
  topBarTitle = 'Youtube Downloader';
  defaultTheme = null;
  allowThemeChange = null;
  allowSubscriptions = false;
  enableDownloadsManager = false;

  @ViewChild('sidenav') sidenav: MatSidenav;
  @ViewChild('notifications') notifications: NotificationsComponent;
  @ViewChild('hamburgerMenu', { read: ElementRef }) hamburgerMenuButton: ElementRef;
  navigator: string = null;

  notification_count = 0;

  constructor(public postsService: PostsService, public snackBar: MatSnackBar, private dialog: MatDialog,
    public router: Router, public overlayContainer: OverlayContainer, private elementRef: ElementRef,
  ) {

    this.navigator = localStorage.getItem('player_navigator');
    // runs on navigate, captures the route that navigated to the player (if needed)
    this.router.events.subscribe((e) => { if (e instanceof NavigationStart) {
      this.navigator = localStorage.getItem('player_navigator');
    } else if (e instanceof NavigationEnd) {
      // blurs hamburger menu if it exists, as the sidenav likes to focus on it after closing
      if (this.hamburgerMenuButton && this.hamburgerMenuButton.nativeElement) {
        this.hamburgerMenuButton.nativeElement.blur();
      }
    }
    });

    this.postsService.config_reloaded.subscribe(changed => {
      if (changed) {
        this.loadConfig();
      }
    });

  }
  ngOnInit(): void {
    const storedTheme = this.getStoredTheme();
    if (storedTheme) {
      this.setTheme(storedTheme);
    }
    
    this.postsService.open_create_default_admin_dialog.subscribe(open => {
      if (open) {
        const dialogRef = this.dialog.open(SetDefaultAdminDialogComponent);
        dialogRef.afterClosed().subscribe(res => {
          if (!res || !res['user']) {
            if (this.router.url !== '/login') { this.router.navigate(['/login']); }
          } else {
            console.error('Failed to create default admin account. See logs for details.');
          }
        });
      }
    });
  }

  ngAfterViewInit(): void {
    this.postsService.sidenav = this.sidenav;
  }

  toggleSidenav(): void {
    this.sidenav.toggle();
  }

  loadConfig(): void {
    // loading config
    this.topBarTitle = this.postsService.config['Extra']['title_top'];
    const themingExists = this.postsService.config['Themes'];
    this.defaultTheme = themingExists ? this.postsService.config['Themes']['default_theme'] : 'default';
    this.allowThemeChange = themingExists ? this.postsService.config['Themes']['allow_theme_change'] : true;
    this.allowSubscriptions = this.postsService.config['Subscriptions']['allow_subscriptions'];
    this.enableDownloadsManager = this.postsService.config['Extra']['enable_downloads_manager'];

    // sets theme to config default if it doesn't exist
    const storedTheme = this.getStoredTheme();
    if (!storedTheme) {
      this.setTheme(themingExists ? this.defaultTheme : 'default');
    } else {
      this.setTheme(storedTheme);
    }

    // gets the subscriptions
    if (this.allowSubscriptions) {
      this.postsService.reloadSubscriptions();
    }

    this.postsService.reloadCategories();

    this.postsService.getVersionInfo().subscribe(res => {
      this.postsService.version_info = res['version_info'];
    });
  }

  // theme stuff

  getThemeStorageKey(): string {
    if (this.postsService.config && this.postsService.config['Advanced'] && this.postsService.config['Advanced']['multi_user_mode'] && this.postsService.user && this.postsService.user.uid) {
      return `theme_${this.postsService.user.uid}`;
    }
    return 'theme';
  }

  getStoredTheme(): string {
    return localStorage.getItem(this.getThemeStorageKey()) || localStorage.getItem('theme');
  }

  setStoredTheme(theme: string): void {
    const key = this.getThemeStorageKey();
    localStorage.setItem(key, theme);
    if (key !== 'theme') {
      localStorage.removeItem('theme');
    }
  }

  setTheme(theme) {
    // theme is registered, so set it to the stored cookie variable
    let old_theme = null;
    if (this.THEMES_CONFIG[theme]) {
        const currentTheme = this.getStoredTheme();
        if (currentTheme) {
          old_theme = currentTheme;
          if (!this.THEMES_CONFIG[old_theme]) {
            console.log('bad theme found, setting to default');
            if (this.defaultTheme === null) {
              // means it hasn't loaded yet
              console.error('No default theme detected');
            } else {
              this.setStoredTheme(this.defaultTheme);
              old_theme = this.getStoredTheme(); // updates old_theme
            }
          }
        }
        this.setStoredTheme(theme);
        this.elementRef.nativeElement.ownerDocument.body.style.backgroundColor = this.THEMES_CONFIG[theme]['background_color'];
    } else {
        console.error('Invalid theme: ' + theme);
        return;
    }

    this.postsService.setTheme(theme);

    this.onSetTheme(this.THEMES_CONFIG[theme]['css_label'], old_theme ? this.THEMES_CONFIG[old_theme]['css_label'] : old_theme);
  }

  onSetTheme(theme, old_theme) {
    if (old_theme) {
      document.body.classList.remove(old_theme);
      this.overlayContainer.getContainerElement().classList.remove(old_theme);
    }
    this.overlayContainer.getContainerElement().classList.add(theme);
    this.componentCssClass = theme;
  }

  flipTheme(): void {
    if (this.postsService.theme.key === 'default') {
      this.setTheme('dark');
    } else if (this.postsService.theme.key === 'dark') {
      this.setTheme('default');
    }
  }

  themeMenuItemClicked(event): void {
    this.flipTheme();
    event.stopPropagation();
  }

  goBack(): void {
    if (!this.navigator) {
      this.router.navigate(['/home']);
    } else {
      this.router.navigateByUrl(this.navigator);
    }
  }

  openSettingsDialog(): void {
    this.dialog.open(SettingsComponent, {
      width: '80vw'
    });
  }

  openAboutDialog(): void {
    this.dialog.open(AboutDialogComponent, {
      width: '80vw'
    });
  }

  openProfileDialog(): void {
    this.dialog.open(UserProfileDialogComponent, {
      width: '60vw'
    });
  }

  openArchivesDialog(): void {
    this.dialog.open(ArchiveViewerComponent, {
      width: '85vw'
    });
  }

  notificationCountUpdate(new_count: number): void {
    this.notification_count = new_count;
  }

  notificationMenuOpened(): void {
    this.notifications.getNotifications();
  }

  notificationMenuClosed(): void {
    this.notifications.setNotificationsToRead();
  }

}
