import {
  Component, Input, OnDestroy, ViewChild,
} from '@angular/core';


import { Observable, of, Subscription } from 'rxjs';
import { catchError, map } from 'rxjs/operators';

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

import { Anim } from './animation';
import { DiscoveryService } from '../service/discovery.service';
import { DiscoverySubscriber, DiscoveryNotify } from '../subscriber/discovery.subscriber';
import { SearchResultComponent } from './search-result.component';
import { SearchFilterComponent } from './search-filter.component';

@Component({
  selector: 'of-discovery',
  templateUrl: './discovery.component.html',
  animations: Anim,
})
export class DiscoveryComponent implements OnDestroy {

  @Input() probeHostID;
  pending$: Observable<boolean>;
  error$: Observable<any>;
  discoverySubscription: Subscription;

  selectedProbe: ProbeHost;
  requested: boolean;
  discoverZone: DiscoverZone;

  filterWord: string;
  filterServices: Service[];

  startDate: Date;
  stopDate: Date;

  @ViewChild('discoveryResult') discoveryResult: SearchResultComponent;
  @ViewChild('discoveryFilter') discoveryFilter: SearchFilterComponent;

  constructor(
    private discoveryService: DiscoveryService,
    private discoverySubscriber: DiscoverySubscriber,
  ) {
    this.discoverySubscription = null;
  }

  ngOnDestroy(): void {
    if (null !== this.discoverySubscription) {
      this.discoverySubscription.unsubscribe();
    }
  }

  onRequestDiscovery(dz: DiscoverZone) {
    this.requested = true;
    this.discoverZone = dz;

    const zone: Zone = {
      network: this.selectedProbe.infraHost.infraZone.network, // this.selectedProbe.probe.cidr
      address: this.selectedProbe.infraHost.infraZone.address.split('/')[0],
      iface: this.selectedProbe.infraHost.infraZone.iface,
      mac: this.selectedProbe.infraHost.infraZone.mac,
      metaIPType: this.selectedProbe.infraHost.infraZone.metaIPType,
    };

    this.discoveryService.discoverHost(this.selectedProbe.probe.probeKey, zone, dz.discoverHost);

    this.discoverySubscription = this.discoverySubscriber.observable().pipe(
      map((discoveryNotify: DiscoveryNotify) => {
        switch (discoveryNotify.method) {
          case 'DiscoveryService.discoveryStart': {
            const startDate = discoveryNotify.params as Date;
            this.discoveryResult.discoveryStarted(startDate);
            break;
          }
          case 'DiscoveryService.discoveryStop': {
            const stopDate = discoveryNotify.params as Date;
            this.discoveryResult.discoveryStopped(stopDate);
            this.discoverySubscription.unsubscribe();
            this.discoverySubscription = null;
            break;
          }
          case 'DiscoveryService.discoveredZone': {
            const _zone = discoveryNotify.params as Zone;
            break;
          }
          case 'DiscoveryService.discoveredHost': {
            const host = discoveryNotify.params as Host;
            this.discoveryResult.addHost(host);
            break;
          }
          case 'DiscoveryService.discoveredPort': {
            const port = discoveryNotify.params as Port;
            // this.discoveryResult.addPort(port);
            break;
          }
          case 'DiscoveryService.discoveredService': {
            const service = discoveryNotify.params as Service;
            this.discoveryFilter.addService(service);
            this.discoveryResult.addService(service);
            break;
          }
          default: {
            break;
          }
        }
      }),
      catchError(error => {
        return of();
      }),
    ).subscribe();
  }

  onRequestStop() {
    this.discoverZone = null;
    this.requested = false;
    this.discoveryService.stopDiscovery(this.selectedProbe.probe.probeKey);
  }
}
