import { Component, HostListener, ViewChild } from '@angular/core';
import { DateAdapter } from '@angular/material/core';
import { Router } from '@angular/router';
import { fromEvent } from 'rxjs';

import { AuthService } from '../../services/auth.service';
import { I18nService } from '../../services/i18n.service';
import { UserService } from '../../services/user.service';

import { SwUpdate } from '@angular/service-worker';
import packageJson from '../../../../package.json';
import { MatSidenav } from '@angular/material/sidenav';
import { DebugService } from 'src/app/services/debug.service';

@Component({
  selector: 'ui-main',
  templateUrl: './main.ui.html',
  styleUrls: ['./main.ui.scss']
})
export class UiMain {

  opened: boolean = true;
  darkTheme: boolean = false;
  title = 'buntspecht';
  currentLocale: String;
  datetimeformat: String;
  locales;
  authenticated: boolean = false;
  username: string = "";
  admin: boolean = false;
  debug: boolean = false;
  hasUpdate: boolean = false;

  touchThresh: number = 150;
  touchStartX: number;
  touchX: number;

  version = packageJson.version;

  @ViewChild('sidenav') sidenav: MatSidenav;

  constructor(
    private i18n: I18nService,
    private authService: AuthService,
    private userService: UserService,
    private debugService: DebugService,
    private router: Router,
    private _adapter: DateAdapter<any>,
    private swUpdate: SwUpdate) {

    this.swUpdate.versionUpdates.subscribe({
      next: (evt) => {
        if (evt.type == 'VERSION_READY') {
          this.hasUpdate = true;
        } else if (evt.type == 'VERSION_INSTALLATION_FAILED') {
          console.error(`Failed to install version '${evt.version.hash}': ${evt.error}`);
        }
      }
    })

    if (this.swUpdate.isEnabled) {
      // check for PWA update every 30s
      setInterval(() => {
        this.swUpdate.checkForUpdate();
      }, 30000);
    }
  }

  async ngOnInit() {
    this.datetimeformat = this.i18n.get('format.datetime', []);
    this.currentLocale = this.i18n.getLocale();
    this.locales = this.i18n.getLocales();
    this.authService.auth.subscribe({
      next: (auth) => {
        this.authenticated = true;
        this.username = auth.username;
        this.admin = auth.authorities && auth.authorities.find((role) => role.authority == 'ROLE_ADMIN') != undefined;
        this.debug = auth.authorities && auth.authorities.find((role) => role.authority == 'ROLE_DEBUG') != undefined;
      },
      error: (error) => {
        this.authenticated = false;
        this.opened = false;
      }
    })

    this._adapter.setLocale(this.currentLocale);

    const width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
    if (width < 768) {
      this.opened = false;
    } else {
      this.opened = true;
    }

    if (localStorage.getItem("buntspecht.darkTheme") == "true") {
      this.darkTheme = true;
      window.document.body.classList.add("dark-theme");
    }

    this.touchEvents();
  }

  setLocale(locale) {
    localStorage.setItem("buntspecht.locale", locale);

    if (this.authenticated) {
      this.userService.get().subscribe({
        next: (user: any) => {
          user.locale = locale;
          this.userService.update(user).subscribe({
            next: () => {
              window.location.reload();
            }
          })
        }
      });
    } else {
      window.location.reload();
    }
  }

  close() {
    this.opened = false;
    this.sidenav.close();
  }

  preventClose(event) {
    event.preventDefault();
    event.stopPropagation();
  }

  toggleDarkTheme() {
    this.darkTheme = !this.darkTheme;

    localStorage.setItem("buntspecht.darkTheme", this.darkTheme ? "true" : "false");

    if (this.authenticated) {
      this.userService.get().subscribe({
        next: (user: any) => {
          user.darkTheme = this.darkTheme;
          this.userService.update(user).subscribe({
            next: () => {
              window.location.reload();
            }
          })
        }
      });
    } else {
      window.location.reload();
    }

  }

  logout() {
    localStorage.removeItem("buntspecht.autologin");
    this.authService.logout().subscribe({
      next: () => {
        this.router.navigate([""]).then(() => {
          window.location.reload();
        });
      }
    })
  }

  isBiggerScreen() {
    const width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
    if (width < 768) {
      return false;
    } else {
      return true;
    }
  }

  openExternal(event, url, target = '_self') {
    window.open(url, target);
    this.preventClose(event);
  }

  @HostListener('window:resize', ['$event'])
  onResize(event) {
    if (event.target.innerWidth < 768) {
      this.opened = false;
    } else {
      this.opened = true;
    }
  }

  touchEvents(): void {
    fromEvent(document, 'touchstart').subscribe({
      next: (event: TouchEvent) => {
        if (event.touches[0]) {
          this.touchStartX = event.touches[0].screenX;
        }
      }
    })

    fromEvent(document, 'touchmove').subscribe({
      next: (event: TouchEvent) => {
        if (event.touches[0]) {
          this.touchX = event.touches[0].screenX;
        }
      }
    })

    fromEvent(document, 'touchend').subscribe({
      next: () => {
        if (this.touchX != 0) {
          const touchDiff = this.touchStartX - this.touchX;
          this.touchStartX = 0;
          this.touchX = 0;
          if (touchDiff < 0 && touchDiff < (this.touchThresh * -1) && !this.opened) {
            this.opened = true;
          } else if (touchDiff > 0 && touchDiff > this.touchThresh && this.opened) {
            this.opened = false;
          }
        }
      }
    })
  }

  updateSw(force: boolean = false): void {
    if (this.hasUpdate || force) {
      if (this.swUpdate.isEnabled) {
        this.swUpdate.activateUpdate().then(() => {
          this.clearAndRefresh();
        });
      } else {
        this.clearAndRefresh();
      }
    }
  }

  clearAndRefresh() {
    if ('caches' in window) {
      caches.keys()
        .then(function (keyList) {
          return Promise.all(keyList.map(function (key) {
            return caches.delete(key);
          }));
        })
    }
    window.location.reload();
  }

  random() {
    console.log("Random?");
    this.debugService.random().subscribe({
      next: () => {
        window.location.reload();
      }
    });
  }
}

