import { Component, EventEmitter, OnDestroy, OnInit } from '@angular/core';
import { MenuItem, PrimeNGConfig } from 'primeng/api';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { TranslateService } from '@ngx-translate/core';
import { GuiService } from 'src/app/service/gui.service';
import { User } from 'src/app/model/auth/user';
import { AuthService } from 'src/app/service/auth.service';
import { MenuElement } from 'src/app/model/view/menu-element';
import { SidebarService } from 'src/app/service/sidebar.service';
import { ConfigService } from 'src/app/service/config.service';
import { UserSettingsService } from 'src/app/service/user-settings.service';
import { SettingsService } from 'src/app/service/settings.service';
import { DataPrivacyService } from 'src/app/service/data-privacy.service';
import { ConfirmationDialogService } from 'src/app/service/confirmation-dialog.service';
import { Logger } from 'src/app/service/logger.service';

const logger = new Logger('Header');

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.scss'],
})
export class HeaderComponent implements OnInit, OnDestroy {
  langList: MenuItem[] = [];
  themeList: MenuItem[] = [];

  userMenuList!: MenuItem[];
  user: User | null = null;
  private unsubscribe$ = new Subject<void>();
  isMobile = window.innerWidth <= 600;

  menu: MenuElement[] = [];

  private langChange: EventEmitter<void> = new EventEmitter<void>();

  constructor(
    private translateService: TranslateService,
    private ngConfig: PrimeNGConfig,
    private guiService: GuiService,
    private auth: AuthService,
    private sidebarService: SidebarService,
    private config: ConfigService,
    private settings: SettingsService,
    private userSettings: UserSettingsService,
    private dataPrivacyService: DataPrivacyService,
    private confirmation: ConfirmationDialogService
  ) {
    this.langChange.subscribe(async () => {
      await this.initUserMenuList();
    });

    this.guiService.isMobile$
      .pipe(takeUntil(this.unsubscribe$))
      .subscribe(isMobile => {
        this.isMobile = isMobile;
        if (isMobile) {
          this.sidebarService.hide();
        }
      });

    this.auth.user$.pipe(takeUntil(this.unsubscribe$)).subscribe(async user => {
      this.user = user;

      await this.loadTheme();
      await this.loadLang();

      this.guiService.loadedGuiSettings$.next(true);
    });

    this.themeList = this.config.settings.themes.map(theme => {
      return {
        label: theme.label,
        command: async () => {
          this.guiService.theme$.next(theme.name);
          await this.userSettings.set('theme', theme.name);
        },
      };
    });
  }

  async ngOnInit() {
    await this.initMenuLists();
  }

  ngOnDestroy() {
    this.unsubscribe$.next();
    this.unsubscribe$.complete();
  }

  async login() {
    await this.auth.login();
  }

  async initMenuLists() {
    await this.initMenuList();
    await this.initLangMenuList();
    await this.initUserMenuList();
  }

  async initMenuList() {
    this.menu = [];
  }

  async initLangMenuList() {
    this.langList = [
      {
        label: 'English',
        command: async () => {
          this.translate('en');
          await this.setLang('en');
        },
      },
      {
        label: 'Deutsch',
        command: async () => {
          this.translate('de');
          await this.setLang('de');
        },
      },
    ];
  }

  async initUserMenuList() {
    this.userMenuList = [
      {
        label: `${this.user?.username}`,
        disabled: true,
        visible: !!this.user,
      },
      {
        label: this.translateService.instant('header.privacy'),
        items: [
          {
            label: this.translateService.instant('privacy.export_data'),
            command: () => {
              if (!this.user) {
                return;
              }
              this.dataPrivacyService.downloadDataExportJson(this.user?.id);
            },
            icon: 'pi pi-download',
          },
          {
            label: this.translateService.instant('privacy.delete_data'),
            command: () => {
              this.confirmation.confirmDialog({
                header: 'privacy.delete_data_header',
                message: 'privacy.delete_data_message',
                accept: () => {
                  if (!this.user) {
                    return;
                  }

                  this.dataPrivacyService
                    .anonymizeData(this.user.id)
                    .subscribe(() => {});
                },
              });
            },
            icon: 'pi pi-trash',
          },
        ],
      },
      {
        label: this.translateService.instant('header.profile'),
        items: [
          {
            label: this.translateService.instant('header.edit_profile'),
            command: () => {
              window.open(
                `${this.config.settings.keycloak.url}/realms/${this.config.settings.keycloak.realm}/account`,
                '_blank'
              );
            },
            icon: 'pi pi-user-edit',
          },
          {
            label: this.translateService.instant('header.logout'),
            command: async () => {
              await this.auth.logout();
            },
            icon: 'pi pi-sign-out',
          },
        ],
      },
    ];
  }

  translate(lang: string) {
    logger.debug('translate', lang);
    this.translateService.use(lang);
    this.translateService
      .get('primeng')
      .subscribe(res => this.ngConfig.setTranslation(res));
    this.langChange.next();
  }

  async loadTheme() {
    const defaultTheme = (await this.settings.get('default_theme')) ?? 'maxlan';
    const userTheme = await this.userSettings.get('theme');
    const theme = userTheme ?? defaultTheme;

    this.guiService.theme$.next(theme);

    if (!userTheme) {
      await this.userSettings.set('theme', theme);
    }
  }

  async loadLang() {
    const defaultLang = (await this.settings.get('default_language')) ?? 'en';
    const userLang = await this.userSettings.get('language');
    const lang = userLang ?? defaultLang;

    this.translate(lang);

    if (userLang) {
      return;
    }
    await this.userSettings.set('language', lang);
  }

  async setLang(lang: string) {
    await this.userSettings.set('language', lang);
  }

  toggleSidebar() {
    if (this.sidebarService.visible$.value) {
      this.sidebarService.hide();
      return;
    }

    this.sidebarService.show();
  }
}
