import { Component, OnInit, Input, AfterContentInit, Output, EventEmitter, OnDestroy, OnChanges, SimpleChanges } from '@angular/core';
import { Store, select, StateObservable } from '@ngrx/store';
import { RPCClientError } from '@loafer/ng-rpc/protocol';
import { Subscription } from 'rxjs/Subscription';
import { TreeNode } from 'primeng/primeng';

import * as DiscoveredStore from 'packages/discovery/store/setting';
import { SettingSelector, DiscoverSelector } from 'packages/discovery/store';
import * as DiscoverStore from 'packages/discovery/store/discover';
import * as RegistStore from 'packages/discovery/store/regist';

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

@Component({
  selector: 'of-discovery-result',
  templateUrl: './result.component.html',
})
export class ResultComponent implements OnInit, AfterContentInit, OnDestroy, OnChanges {

  @Input() started: boolean;

  treeNodes = [];
  selectedNodes = [];
  zones: Map<string, Zone> = null;
  checkedSet = new Set();

  resultSubscription$: Subscription;
  result$: any;
  startedSubscription$: Subscription;
  started$: any;
  endedSubscription$: Subscription;
  ended$: any;

  inProgress = false;


  selectedDiscoveryResult: TreeNode[];

  constructor(
    private discoverdStore: Store<DiscoveredStore.State>,
    private discoverStore: Store<DiscoverStore.State>,
    private registStore: Store<RegistStore.State>,
  ) {
    this.result$ = discoverStore.pipe(select(DiscoverSelector.select('zones')));
    this.started$ = discoverStore.pipe(select(DiscoverSelector.select('isStart')));
    this.ended$ = discoverStore.pipe(select(DiscoverSelector.select('isEnd')));
  }

  ngOnInit() {
    this.inProgress = true;
    this.resultSubscription$ = this.result$.subscribe(
      (zones: Map<string, Zone>) => {
        if (zones !== undefined && zones !== null) {
          console.log(zones);
          this.treeNodes = this.convertTreeViewZone(zones);
          this.zones = zones;
        }
      },
      (error: RPCClientError) => {
        console.log(error.response.message);
      }
    );
    this.startedSubscription$ = this.started$.subscribe(
      (isStart: boolean) => {
        if (isStart !== undefined && isStart !== null && isStart) {
          console.log('##Discovery has started.##');
        }
      },
      (error: RPCClientError) => {
        console.log(error.response.message);
      }
    );
    this.endedSubscription$ = this.ended$.subscribe(
      (isEnd: boolean) => {
        if (isEnd !== undefined && isEnd !== null && isEnd) {
          console.log('##Discovery has done.##');
        }
      },
      (error: RPCClientError) => {
        console.log(error.response.message);
      }
    );
  }

  ngAfterContentInit() {
  }

  ngOnChanges(changes: SimpleChanges): void {
    if (changes['started'] && !changes['started'].currentValue) {
      this.inProgress = false;
    }
  }

  ngOnDestroy() {
    if (this.startedSubscription$) {
      this.startedSubscription$.unsubscribe();
    }
    if (this.endedSubscription$) {
      this.endedSubscription$.unsubscribe();
    }
    if (this.resultSubscription$) {
      this.resultSubscription$.unsubscribe();
    }
  }

  save() {
  }

  convertTreeViewZone(zones: Map<string, Zone>) {

    if (zones === undefined || zones === null) {
      return;
    }

    const treeNodes: any[] = [];

    zones.forEach((value: Zone, key: string, map) => {
      const jZone: any = {
        label: 'Zone - ' + value.iface,
        // className: 'cn' + value.ip,
        expandedIcon: 'fa-folder-open',
        collapsedIcon: 'fa-folder',
      };
      jZone.obj = value;
      jZone.children = this.convertViewHost(value.hosts);
      treeNodes.push(jZone);
    });

    return treeNodes;
  }

  convertViewHost(hosts): any[] {
    if (hosts === undefined || hosts === null) {
      return null;
    }
    const hostNodes: any[] = [];

    hosts.forEach((host, hostKey) => {

      const jHost: any = {
        label: 'Host - ' + host.ipv4,
        // className: 'cn' + host.ip
        expandedIcon: 'fa-folder-open',
        collapsedIcon: 'fa-folder',
      };
      jHost.obj = host;
      jHost.children = this.convertViewPort(host.ports);
      hostNodes.push(jHost);

    });

    return hostNodes;

  }

  convertViewPort(ports): any[] {
    if (ports === undefined || ports === null || ports.size < 0) {
      return null;
    }
    const portChildren: any[] = [];
    ports.forEach((port, portKey) => {
      const jPort: any = {
        label: 'Port - ' + port.portNumber,
        // className: 'cn' + port.portNumber,
        expandedIcon: 'fa-folder-open',
        collapsedIcon: 'fa-folder',
      };
      jPort.obj = port;
      jPort.children = this.convertViewService(port.services);
      portChildren.push(jPort);
    });

    return portChildren;
  }

  convertViewService(services): any[] {
    if (services === undefined || services === null || services.size <= 0) {
      return null;
    }
    const serviceChildren: any[] = [];
    services.forEach((service, serviceKey) => {
      const jService: any = {
        label: 'Service - ' + service.serviceName,
        // className: 'cn' + service.serviceName,
      };
      jService.obj = service;

      serviceChildren.push(jService);
    });

    return serviceChildren;
  }


}
