import { Injectable } from '@angular/core';
import { interval, Subject, Subscription } from 'rxjs';
import { AppLogsService } from '../applogs.service';
import { EN_UINotificationType, UINotification } from './uinotification';
import { MatSnackBar, MatSnackBarConfig, MatSnackBarHorizontalPosition, MatSnackBarRef, MatSnackBarVerticalPosition, TextOnlySnackBar } from '../../components/angular-material-index';


const cnst_NotifierNachrichtDauer = 1000;
const nachrichtVisible = true;

class HenselMatSnackBarConfig extends (MatSnackBarConfig) {
  constructor(obj: any) {
    super();
    Object.assign(this, obj);
  }
}

@Injectable({
  providedIn: 'root'
})
export class UINotifierService {
  private readonly MAX_INACTIVE_ITEMS: number = 5;
  private activeItems: UINotification[];
  private inactiveItems: UINotification[];
  private idCounter: number;

  msbPoxPosition: { horizontal: MatSnackBarHorizontalPosition, vertical: MatSnackBarVerticalPosition } = { horizontal: 'center', vertical: 'bottom' };

  public data$: Subject<UINotification>;
  public isActive: boolean = true;
  protected pollingItervalTimer: Subscription = null;
  private currentSnackBar: MatSnackBarRef<TextOnlySnackBar>;

  constructor(
    private appLogsService: AppLogsService,
    public snackBar: MatSnackBar,
  ) {
    this.data$ = new Subject<UINotification>();
    this.data$.subscribe((lastNotification: UINotification) => this.showNotification(lastNotification));

    this.activeItems = [];
    this.inactiveItems = [];
    this.idCounter = 1;
  }


  stopPolling() {
    this.hide();
    this.pollingItervalTimer?.unsubscribe();
    this.pollingItervalTimer = null;
  }


  startPolling() {
    if (!this.pollingItervalTimer) this.pollingItervalTimer = interval(100).subscribe(this.checkinOnTimer);
  }


  private checkinOnTimer = () => {
    if (this.activeItems.length === 0) {
      this.stopPolling();
    } else {
      // this.appLogsService.dlog('->timer active:' + this.activeItems.length + ', inactive' + this.inactiveItems.length);
      const start = new Date().getTime();
      let item = this.activeItems[0];
      if (item.durationExpired(start)) {
        this.stopMessage(item.id);
        if (this.activeItems.length > 0) item = this.activeItems[0];
      }
      if (item && !item.displayedTimestamp) this.data$.next(item);
      // this.appLogsService.dlog('<-timer active:' + this.activeItems.length + ', inactive' + this.inactiveItems.length);
    }
  }



  // remove last MAX_INACTIVE_ITEMS
  cleanUp(item: UINotification) {
    const index: number = this.activeItems.indexOf(item);
    if (index !== -1) this.activeItems.splice(index, 1);
    this.inactiveItems.splice(0, 0, item); // neueste zuerst

    if (this.inactiveItems.length > this.MAX_INACTIVE_ITEMS) {
      this.inactiveItems.splice(this.MAX_INACTIVE_ITEMS);
    }

  }

  clearAll() {
    this.activeItems = [];
    this.inactiveItems = [];
  }

  private createNew(message: string, type: EN_UINotificationType, duration: number): UINotification {
    this.idCounter++;
    return new UINotification(message, type, duration, this.idCounter);
  }

  public getActiveItems(): UINotification[] {
    return this.activeItems;
  }

  public getInactiveItems(): UINotification[] {
    return this.inactiveItems;

  }
  public isVisible(): boolean {
    return this.activeItems.length > 0;
  }

  public getInactiveMessages(): string {
    let msg = '';
    this.inactiveItems.forEach((item: UINotification) => {
      msg += item.message + '; ';
    });

    return msg;
  }

  public getActiveMessages(): string {
    let msg = '';
    this.activeItems.forEach((item: UINotification) => {
      msg += item.message + '; ';
    });
    return msg;
  }

  // return: new id
  public showMessage(message: string, msgId?: number, duration: number = cnst_NotifierNachrichtDauer): number {
    return this.add2Queue(message, msgId, duration, EN_UINotificationType.info);
  }

  public showWarning(message: string, msgId?: number, duration: number = cnst_NotifierNachrichtDauer): number {
    return this.add2Queue(message, msgId, duration, EN_UINotificationType.warn);
  }

  private add2Queue(message: string, msgId: number, duration: number = cnst_NotifierNachrichtDauer, notifType: EN_UINotificationType): number {
    if (!this.isActive) return;
    if (msgId) { this.stopMessage(msgId); }
    const item = this.createNew(message, notifType, duration);
    if (this.activeItems.length > 0) {
      const lastWaitingItim = this.activeItems[this.activeItems.length - 1];
      if (!lastWaitingItim.displayedTimestamp) lastWaitingItim.duration /= 4;
    }
    this.activeItems.push(item);
    this.startPolling();
    return item.id;
  }

  public stopMessage(id: number) {
    const foundItem = this.activeItems.find((item: UINotification) => item.id === id);
    if (foundItem) {
      foundItem.stopMessage();
      this.cleanUp(foundItem);
    }
  }

  public updateMessage(id: number, message: string) {
    this.appLogsService.dlog('updateMessage id:' + id + ' ' + message);
    const foundedItem = this.activeItems.filter((item: UINotification) => item.id === id);
    if (foundedItem && foundedItem[0]) {
      this.appLogsService.dlog('found updateMessage id:' + id + ' ' + message);

      foundedItem[0].message = message;
    }
  }

  hide() {
    this.appLogsService.dlog('<-Hide Message');
    this.snackBar.dismiss();
  }


  showNotification(lastNotification: UINotification): void {
    this.hide();
    lastNotification.displayedTimestamp = new Date();
    this.currentSnackBar = this.snackBar.open(lastNotification.message, undefined, new HenselMatSnackBarConfig(
      {
        horizontalPosition: this.msbPoxPosition.horizontal,
        verticalPosition: this.msbPoxPosition.vertical,
        duration: lastNotification.duration,
        panelClass: 'hensel-notifier'
      }
    ));
    this.appLogsService.dlog('Show Message id:' + lastNotification.id + ' ' + lastNotification.message);
  }
}
