/*
 * Copyright (C) 2023 StApps
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */
import {AfterContentInit, Component, NgZone} from '@angular/core';
import {Router} from '@angular/router';
import {App, URLOpenListenerEvent} from '@capacitor/app';
import {Platform, ToastController} from '@ionic/angular/standalone';
import {SettingsProvider} from './modules/settings/settings.provider';
import {InAppReviewProvider} from './modules/settings/in-app-review/in-app-review.provider';
import {AuthHelperService} from './modules/auth/auth-helper.service';
import {environment} from '../environments/environment';
import {Capacitor} from '@capacitor/core';
import {ScheduleSyncService} from './modules/background/schedule/schedule-sync.service';
import {Keyboard, KeyboardResize} from '@capacitor/keyboard';
import {AppVersionService} from './modules/about/app-version.service';
import {SplashScreen} from '@capacitor/splash-screen';

/**
 * TODO
 */
@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
})
export class AppComponent implements AfterContentInit {
  /**
   * TODO
   */
  pages: Array<{
    /**
     * TODO
     */
    component: unknown;
    /**
     * TODO
     */
    title: string;
  }>;

  /**
   * Angular component selectors that should not infulence keyboard state
   */
  ommitedEventSources = ['ion-input', 'ion-searchbar'];

  constructor(
    private readonly platform: Platform,
    private readonly settingsProvider: SettingsProvider,
    private readonly inAppReviewProvider: InAppReviewProvider,
    private readonly router: Router,
    private readonly zone: NgZone,
    private readonly authHelper: AuthHelperService,
    private readonly toastController: ToastController,
    private readonly scheduleSyncService: ScheduleSyncService,
    private readonly versionService: AppVersionService,
  ) {
    void this.initializeApp();
  }

  async ngAfterContentInit() {
    this.scheduleSyncService.init();
    void this.scheduleSyncService.enable();
    this.versionService.getPendingReleaseNotes().then(notes => {
      if (notes) {
        this.versionService.presentReleaseNotes(notes);
      }
    });

    if (document.readyState === 'complete') {
      this.hideSplash();
    } else {
      document.addEventListener('readystatechange', () => {
        if (document.readyState === 'complete') this.hideSplash();
      });
    }
  }

  async hideSplash() {
    if (Capacitor.isNativePlatform()) {
      void SplashScreen.hide();
      await this.inAppReviewProvider.increaseSessionCount();
      void this.inAppReviewProvider.startInAppReviewIfFeasible();
    }
  }

  /**
   * TODO
   */
  async initializeApp() {
    App.addListener('appUrlOpen', (event: URLOpenListenerEvent) => {
      this.zone.run(() => {
        const slug = event.url.split(environment.app_host).pop();
        if (slug) {
          this.router.navigateByUrl(slug);
        }
        // If no match, do nothing - let regular routing
        // logic take over
      });
    });
    this.platform.ready().then(async () => {
      await this.authNotificationsInit();
      // set order of categories in settings
      this.settingsProvider.setCategoriesOrder(['profile', 'privacy', 'credentials', 'others']);
    });

    window.addEventListener('touchmove', this.touchMoveEvent, true);
    if (Capacitor.getPlatform() === 'ios') {
      Keyboard.setResizeMode({mode: KeyboardResize.None});
    }
  }

  private async authNotificationsInit() {
    this.authHelper
      .getProvider('default')
      .events$.subscribe(action => this.showMessage(this.authHelper.getAuthMessage('default', action)));
    this.authHelper
      .getProvider('paia')
      .events$.subscribe(action => this.showMessage(this.authHelper.getAuthMessage('paia', action)));
  }

  private async showMessage(message?: string) {
    if (message === undefined) {
      return;
    }
    const toast = await this.toastController.create({
      message: message,
      duration: 2000,
      color: 'success',
    });
    await toast.present();
  }

  /**
   * Checks if keyboard should be dissmissed
   */
  touchMoveEvent = (event: Event): void => {
    if (
      this.ommitedEventSources.includes(
        (event?.target as unknown as Record<string, string>)?.['s-hn']?.toLowerCase(),
      )
    ) {
      return;
    }
    this.unfocusActiveElement();
  };

  /**
   * Loses focus on the currently active element (meant for input fields).
   * Results in virtual keyboard being dissmissed on native and web plattforms.
   */
  unfocusActiveElement() {
    const activeElement = document.activeElement;
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    (activeElement as any)?.blur();
  }
}
