import { DOCUMENT } from '@angular/common';
import { Component, Inject, OnInit, Renderer2 } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { SwUpdate, UpdateAvailableEvent } from '@angular/service-worker';
import { ApplicationService } from '@core/application';
import { Config } from '@core/config';
import { NotificationsHub } from '@hub/notifications';
import packageInfo from 'package';
import { interval, Observable, Subscription } from 'rxjs';
import { tap } from 'rxjs/operators';
import { Platform } from '@angular/cdk/platform';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit {
  private _checkForUpdates: number = this._config.get('checkForUpdates');
  updateAvailableObs: Observable<UpdateAvailableEvent>;

  get checkForUpdates(): number {
    return this._checkForUpdates;
  }

  // For Unit Testing
  set checkForUpdates(time: number) {
    this._checkForUpdates = time;
  }

  subscriptions = new Subscription();

  constructor(
    private readonly _config: Config,
    private readonly _title: Title,
    private readonly _appService: ApplicationService,
    @Inject(DOCUMENT) private readonly _document: Document,
    private readonly _renderer: Renderer2,
    private readonly _swUpdate: SwUpdate,
    private readonly _notifications: NotificationsHub,
    private readonly _platform: Platform
  ) {
    this.updateClient();
  }

  ngOnInit() {
    this.setTitle();
    this.logVersion();
    this.determinePlatform();

    this._appService.getSection$().subscribe(this.sectionChangeHandler.bind(this));
  }

  setTitle() {
    this._title.setTitle(this._config.get('title'));
  }

  logVersion() {
    console.log(`%c${this._config.get('title')}\r\nVersion: ${packageInfo.version}`, 'font-weight: bold; font-size: 20px;');
  }

  determinePlatform() {
    if (this._platform.IOS && !this._platform.SAFARI) {
      this._renderer.addClass(this._document.body, 'tablet');
      this._renderer.addClass(this._document.body, 'tablet-native');
    } else if (this._platform.IOS && this._platform.SAFARI) {
      this._renderer.addClass(this._document.body, 'tablet');
      this._renderer.addClass(this._document.body, 'tablet-browser');
    } else if (this._platform.isBrowser) {
      this._renderer.addClass(this._document.body, 'desktop');
    }
  }

  sectionChangeHandler(section: string) {
    if (section === 'customer') {
      this._renderer.removeClass(this._document.body, 'branch');
      this._renderer.addClass(this._document.body, 'customer');
    } else if (section === 'branch') {
      this._renderer.removeClass(this._document.body, 'customer');
      this._renderer.addClass(this._document.body, 'branch');
    }
  }

  // --------------------------------------------------------
  // Implementation before Angular Version 13.x.x

  async updateClient() {
    if (!this._swUpdate.isEnabled) {
      return;
    }

    await this.initialCheckForUpdate();
    this.checkForUpdateInterval();
  }

  checkForUpdateInterval() {
    this.updateAvailableObs = this._swUpdate.available.pipe(
      tap((availableEvent) => {
        if (availableEvent?.current?.hash !== availableEvent?.available?.hash) {
          this._notifications.updateNotification();
          this.subscriptions.unsubscribe();
        }
      })
    );
    this.subscriptions.add(
      interval(this._checkForUpdates).subscribe(async () => {
        await this._swUpdate.checkForUpdate();
      })
    );
  }

  async initialCheckForUpdate() {
    this.updateAvailableObs = this._swUpdate.available.pipe(
      tap((availableEvent) => {
        if (availableEvent?.current?.hash !== availableEvent?.available?.hash) {
          location.reload();
        }
      })
    );
    this.subscriptions.add(this.updateAvailableObs.subscribe());
    await this._swUpdate.checkForUpdate();
  }

  // --------------------------------------------------------
  // Implementation for Angular Version 13.x.x

  // updateClient() {
  //   if (!this._swUpdate.isEnabled) {
  //     return;
  //   }

  //   this.initialCheckForUpdate();
  //   this.checkForUpdate();
  // }

  // checkForUpdate() {
  //   interval(this._checkForUpdates).subscribe(() => {
  //     this._swUpdate.checkForUpdate().then((value) => {
  //       if (value) {
  //         this._notifications.updateNotification();
  //       }
  //     });
  //   });
  // }

  // initialCheckForUpdate() {
  //   this._swUpdate.checkForUpdate().then((value) => {
  //     if (value) {
  //       location.reload();
  //     }
  //   });
  // }
}
