import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { catchError, exhaustMap, map, tap } from 'rxjs/operators';

import { RPCSubscriber } from '@loafer/ng-rpc';
import { LoggerService } from '@loafer/ng-logger';

import {
  Zone,
  Host,
  Port,
  Service,
} from '@overflow/commons-typescript/model/discovery';

export interface DiscoveryNotify {
  method: string;
  params: Date | Zone | Host | Port | Service;
}

export class DiscoverySubscriberSubject extends Subject<DiscoveryNotify> {

}

@Injectable()
export class DiscoverySubscriber {
  discoverySubscriberSubject: DiscoverySubscriberSubject;

  public constructor(
    private loggerService: LoggerService,
  ) {
    this.discoverySubscriberSubject = null;
  }

  public observable(): Observable<DiscoveryNotify> {
    if (null === this.discoverySubscriberSubject) {
      this.discoverySubscriberSubject = new DiscoverySubscriberSubject();
    }
    return this.discoverySubscriberSubject.asObservable();
  }

  private publish(method: string, params: any): void {
    this.discoverySubscriberSubject.next({ method: method, params: params });
  }

  @RPCSubscriber({ method: 'DiscoveryService.discoveryStart' })
  public discoveryStart(startDate: Date): void {
    this.loggerService.debug('DiscoverySubscriber.discoveryStart startDate:', startDate);

    this.publish('DiscoveryService.discoveryStart', startDate);
  }

  @RPCSubscriber({ method: 'DiscoveryService.discoveryStop' })
  public discoveryStop(stopDate: Date): void {
    this.loggerService.debug('DiscoverySubscriber.discoveryStop stopDate:', stopDate);

    this.publish('DiscoveryService.discoveryStop', stopDate);
  }


  @RPCSubscriber({ method: 'DiscoveryService.discoveredZone' })
  public discoveredZone(zone: Zone): void {
    this.loggerService.debug('DiscoverySubscriber.discoveredZone zone:', zone);

    this.publish('DiscoveryService.discoveredZone', zone);
  }
  @RPCSubscriber({ method: 'DiscoveryService.discoveredHost' })
  public discoveredHost(host: Host): void {
    this.loggerService.debug('DiscoverySubscriber.discoveredHost host:', host);

    this.publish('DiscoveryService.discoveredHost', host);
  }
  @RPCSubscriber({ method: 'DiscoveryService.discoveredPort' })
  public discoveredPort(port: Port): void {
    this.publish('DiscoveryService.discoveredPort', port);
  }
  @RPCSubscriber({ method: 'DiscoveryService.discoveredService' })
  public discoveredService(service: Service): void {
    this.loggerService.debug('DiscoverySubscriber.discoveredService service:', service);
    this.publish('DiscoveryService.discoveredService', service);
  }
}