import { inject, Injectable } from '@angular/core';
import { NgxSpinnerService } from 'ngx-spinner';
import { Globals } from './globals';
import { AppLogsService } from './applogs.service';
import { EN_AppColors } from '../consts';
import { Subject, BehaviorSubject } from 'rxjs';
import { HenselTranslateService } from './localization/hensel-translate.service';

@Injectable({
  providedIn: 'root'
})

export class PageLoadingService {
  public static delayBackgroundPageLoaded = 750; // timeout in msis needed to correctly process page loadings without delays (with not completed filter)
  public spinnerVisible: number = 0;
  public forgroundLoading$ = new BehaviorSubject<void>(null);
  public backgroundLoading$ = new BehaviorSubject<void>(null);
  public pageActive$ = new Subject<string>();
  private _noOfHttpQueries4Page: number[] = [];
  public get noOfHttpQueries4Page(): number[] {
    return this._noOfHttpQueries4Page;
  }
  public set noOfHttpQueries4Page(value: number[]) {
    value.forEach((vl: number, index: number) => { if (this._noOfHttpQueries4Page[index] > - 1) this._noOfHttpQueries4Page[index] = vl; });
  }

  private startBackgroundLoading: boolean = false;
  private waitBackgroundLoadingFinished: boolean = false;

  private arLoadedCompletedCallBacks: (() => void)[] = [];
  private translationService = inject(HenselTranslateService);
  private _onPageLoagingWaitBackgroundLoadingFinished: boolean = false;
  public get onPageLoagingWaitBackgroundLoadingFinished(): boolean {
    return this._onPageLoagingWaitBackgroundLoadingFinished;
  }
  public set onPageLoagingWaitBackgroundLoadingFinished(value: boolean) {
    this._onPageLoagingWaitBackgroundLoadingFinished = value;
    this.waitBackgroundLoadingFinished = value;
  }
  public startBackgroundLoadingAfterPageIsLoaded: boolean = true;


  constructor(
    private globals: Globals,
    private appLogsservice: AppLogsService,
    private spinnerService: NgxSpinnerService,
  ) {
    this.globals.appPages.forEach(_ => this.noOfHttpQueries4Page.push(-1)); //page is not loaded
  }


  public startSpinner(_startBackgroundLoading: boolean = true, callbackCompleted?: () => void) {
    this.startBackgroundLoading = _startBackgroundLoading || this.startBackgroundLoading;
    // if (!_startBackgroundLoading) this.waitBackgroundLoadingFinished = this.onPageLoagingWaitBackgroundLoadingFinished;
    if (callbackCompleted) this.arLoadedCompletedCallBacks.push(callbackCompleted);
    this.showSpinner();
  }


  public showSpinner() {
    if (this.spinnerVisible++ === 0) {
      this.appLogsservice.dlog('%cshow spinner', { guid: 'spinner' }, 'color:' + EN_AppColors.hideSpinnerColor);
      this.spinnerService.show();
    }
  }


  private allData4PageAreLoaded(page: number = -1): boolean {
    if (page > -1 && page < this.noOfHttpQueries4Page.length) {
      //wait only on this page
      return this.noOfHttpQueries4Page[page] <= 0;
    }
    return this.noOfHttpQueries4Page.every(_ => _ <= 0);
  }


  updatePageLoadedCounters(page: number) {
    if (page !== null) {
      const currentPageIndex: number = (this.globals.isTheLoginPage(this.globals.appPages[page].path) ? page : this.globals.getPageIndex(this.globals.currentPage));

      if (this.noOfHttpQueries4Page[page] > 0) this.noOfHttpQueries4Page[page]--;
      // this.appLogsservice.dlog('-----', page, currentPageIndex, this.noOfHttpQueries4Page);

      if (page < this.noOfHttpQueries4Page.length && this.noOfHttpQueries4Page[page] === 0) {
        //if the page data were loaded
        this.appLogsservice.dlog('%c' + this.translationService.instant(this.globals.appPages[page].messageCaption) + ' data are loaded', 'color:brown');
      }

      if (currentPageIndex === page && !this.startBackgroundLoadingAfterPageIsLoaded) this.doBackgroundLoading();

      if (this.allData4PageAreLoaded(this.waitBackgroundLoadingFinished ? -1 : currentPageIndex /* if onPageLoagingWaitBackgroundLoadingFinished all pages must be loaded before spinner hides*/)) {
        // if (!this.waitBackgroundLoadingFinished) this.spinnerVisible = 1; //to hide spinner anyway
        setTimeout(() => {
          this.hideSpinner();
          this.doCallBacks();
          // this.spinnerVisible = 0;
          this.waitBackgroundLoadingFinished = this.onPageLoagingWaitBackgroundLoadingFinished;
          if (currentPageIndex === page && this.startBackgroundLoadingAfterPageIsLoaded) {
            this.spinnerVisible += 1;  //don't show spinner for background loading
            this.waitBackgroundLoadingFinished = true;
            this.doBackgroundLoading();
            this.spinnerVisible -= 1;  //correcture
          }
        }, PageLoadingService.delayBackgroundPageLoaded); // timeout is needed to correctly process page loadings without delays (with not completed filter)
      }
    }

  }

  private doBackgroundLoading() {
    if (this.startBackgroundLoading) {
      //if the first http-call on the active page returned (only one time)
      this.startBackgroundLoading = false;
      this.backgroundLoading$.next();
    }
  }


  public hideSpinner() {
    if ((this.spinnerVisible > 0) && (--this.spinnerVisible === 0)) {
      this.appLogsservice.dlog('%chide spinner', { guid: 'spinner' }, 'color:' + EN_AppColors.hideSpinnerColor);
      this.spinnerService.hide();
    }
  }


  private doCallBacks() {
    const arLoadedCompletedCallBacks = this.arLoadedCompletedCallBacks;
    this.arLoadedCompletedCallBacks = [];
    arLoadedCompletedCallBacks.forEach((callback) => {if (callback) callback(); });
  }
}
