import { Component } from '@angular/core';
import { AlarmRealtimeService, EventRealtimeService, ManagedObjectRealtimeService, MeasurementRealtimeService, OperationBulkRealtimeService, OperationRealtimeService, RealtimeMessage, RealtimeService } from '@c8y/ngx-components';
import { merge, Observable } from 'rxjs';
import { map, scan } from 'rxjs/operators';

@Component({
  selector: 'cmp-realtime-tutorial',
  templateUrl: './realtime-tutorial.component.html',
  providers: [
    ManagedObjectRealtimeService,
    OperationRealtimeService,
    OperationBulkRealtimeService,
    MeasurementRealtimeService,
    AlarmRealtimeService,
    EventRealtimeService
  ]
})
export class RealtimeTutorialComponent {
  allAPIsRealtime$: Observable<Array<RealtimeMessage<unknown>>>;
  services: Array<{className: string, instance: RealtimeService<unknown>}> = [];
  bufferSize = 10;
  bufferSizeOptions = [1, 5, 10, 25, 50, 100];

  constructor(
    public moRealtime: ManagedObjectRealtimeService,
    public operationRealtime: OperationRealtimeService,
    public operationBulkRealtime: OperationBulkRealtimeService,
    public measurementRealtime: MeasurementRealtimeService,
    public alarmRealtime: AlarmRealtimeService,
    public eventRealtime: EventRealtimeService,
  ) {
    this.services = [
      {
        className: 'ManagedObjectRealtimeService',
        instance: moRealtime
      },
      {
        className: 'OperationRealtimeService',
        instance: operationRealtime
      },
      {
        className: 'OperationBulkRealtimeService',
        instance: operationBulkRealtime
      },
      {
        className: 'MeasurementRealtimeService',
        instance: measurementRealtime
      },
      {
        className: 'AlarmRealtimeService',
        instance: alarmRealtime
      },
      {
        className: 'EventRealtimeService',
        instance: eventRealtime
      },
    ];

    /**
     * Always subscribing for all realtime notifications might generate a lot of traffic/load.
     * For that reason try to provide your entityId where ever it is possible in your production code.
     */
    this.allAPIsRealtime$ = merge(
      ...this.services.map(service => service.instance.onAll$())
    ).pipe(
      scan((acc, val) => {
        acc.push(val);
        return acc.slice(this.bufferSize * -1);
      }, []),
      map(messages => [...messages].reverse())
    );

    // disable every service except the first one
    this.services.forEach((service, index) => {
      if (index) {
        service.instance.stop();
      }
    });
  }

}
