import { Component, OnInit, AfterContentInit, Output, EventEmitter, Input, OnDestroy } from '@angular/core';
import { Store, select, StateObservable } from '@ngrx/store';
import { RPCClientError } from '@loafer/ng-rpc/protocol';
import {
  DiscoveryStartInfo,
  DiscoverZone,
  Zone,
  DiscoverPort,
  DiscoverService
} from '@overflow/commons-typescript/model/discovery';
import * as CIDR from 'ip-cidr';
import * as DiscoveredStore from '../../store/setting';
import { SettingSelector, DiscoverSelector } from '../../store';
import * as DiscoverStore from '../../store/discover';
import * as RegistStore from '../../store/regist';
import { Host } from '@overflow/commons-typescript/model/discovery';
import { Port } from '@overflow/commons-typescript/model/discovery';
import { Service } from '@overflow/commons-typescript/model/discovery';
import * as ProbeDetailStore from 'packages/probe/store';
import { Probe } from '@overflow/commons-typescript/model/probe';
import { TreeNode } from 'primeng/primeng';
import { ListSelector as ProbeListSelector } from 'packages/probe/store';
import * as ProbeListStore from 'packages/probe/store/list';
import { AuthSelector } from 'packages/member/store';
import { Domain } from '@overflow/commons-typescript/model/domain';
import { Subscription } from 'rxjs/Subscription';

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

  @Input() probe: Probe;  /* To determine valid range. */
  @Output() close = new EventEmitter();

  settingSucceed$: any;
  discoveryResult$: any;

  discoveryReq$: any;
  discoveryStart$: any;
  discoveryEnd$: any;

  started = false;

  startIP;
  endIP;
  startPort;
  endPort;
  hostChecked = ['host'];
  portChecked = [];
  serviceChecked = [];
  tcpChecked = true;
  udpChecked = true;
  includeServices = [];

  treeNodes = [];
  selectedNodes = [];
  zones: Map<string, Zone> = null;

  checkedSet = new Set();

  testObj: any[] = testDiscovery;
  selectedDiscoveryResult: TreeNode[];

  constructor(
    private discoverdstore: Store<DiscoveredStore.State>,
    private discoverstore: Store<DiscoverStore.State>,
    private registStore: Store<RegistStore.State>,
    private probeListStore: Store<ProbeListStore.State>
  ) {
    this.settingSucceed$ = discoverdstore.pipe(select(SettingSelector.select('isStart')));
    this.discoveryResult$ = discoverstore.pipe(select(DiscoverSelector.select('zones')));
    this.discoveryReq$ = discoverstore.pipe(select(DiscoverSelector.select('isReq')));
    this.discoveryStart$ = discoverstore.pipe(select(DiscoverSelector.select('isStart')));
    this.discoveryEnd$ = discoverstore.pipe(select(DiscoverSelector.select('isEnd')));
  }

  ngOnInit() {

    // this.settingSucceed$.subscribe(
    //   (succeed: boolean) => {
    //     if (succeed) {
    //       this.started = true;
    //     }
    //   },
    //   (error: RPCClientError) => {
    //     console.log(error.response.message);
    //   }
    // );

    // this.discoveryResult$.subscribe(
    //   (zones: Map<string, Zone>) => {

    //     if (zones !== undefined && zones !== null) {
    //       console.log('ZoneZoneZoneZoneZoneZoneZone');
    //       // console.log(JSON.stringify(zones));
    //       this.treeNodes = this.convertTreeViewZone(zones);
    //       this.zones = zones;
    //     }

    //   },
    //   (error: RPCClientError) => {
    //     console.log(error.response.message);
    //   }
    // );

    // this.discoveryReq$.subscribe(
    //   (isReq: boolean) => {

    //     if (isReq !== undefined && isReq !== null) {
    //       console.log('isReqisReqisReqisReq');
    //     }

    //   },
    //   (error: RPCClientError) => {
    //     console.log(error.response.message);
    //   }
    // );

    // this.discoveryStart$.subscribe(
    //   (isStart: boolean) => {

    //     if (isStart !== undefined && isStart !== null) {
    //       console.log('isStartisStartisStart');
    //     }

    //   },
    //   (error: RPCClientError) => {
    //     console.log(error.response.message);
    //   }
    // );

    // this.discoveryEnd$.subscribe(
    //   (isEnd: boolean) => {

    //     if (isEnd !== undefined && isEnd !== null) {
    //       console.log('isEndisEndisEndisEnd');
    //     }

    //   },
    //   (error: RPCClientError) => {
    //     console.log(error.response.message);
    //   }
    // );
  }

  ngAfterContentInit() {
    if (this.probe === undefined || this.probe === null) {
    } else {
      this.hostRange();
      this.portRange();
    }
  }

  ngOnDestroy() {
  }


  onProbeSelect(event) {
    this.probe = event.value;
    this.hostRange();
    this.portRange();
  }

  closeDialog() {
    this.close.emit();
  }

  isZone(zone: Zone): boolean {

    // for (let i = 0; i < this.treeNodes.length; ++i) {
    //   if (zone.iface === this.treeNodes[i].iface) {
    //     return true;
    //   }
    // }

    return false;
  }


  hostRange() {
    const cidr = new CIDR(this.probe.cidr);
    if (!cidr.isValid()) {
      alert('Invalid cidr : ' + this.probe.cidr);
      return;
    }
    this.startIP = cidr.addressStart.address;
    this.endIP = cidr.addressEnd.address;
  }

  portRange() {
    this.startPort = '1';
    this.endPort = '1024';
  }

  handleHostCheckChange(e: any) {
    this.hostChecked = ['host'];
  }

  handlePortCheckChange(e: any) {
    this.serviceChecked = [];
  }

  handleServiceCheckChange(e: any) {
    if (e) {
      this.portChecked = ['port'];
    }
  }

  handleServiceChange(list: any) {
    this.includeServices = list;
  }

  discovery() {
    console.log(this.startIP);
    console.log(this.startPort);
    console.log(this.endPort);

    let discoverPort: DiscoverPort = null;
    let discoverService: DiscoverService = null;

    if (this.serviceChecked.length > 0) {
      const services = new Array();
      for (const service of this.includeServices) {
        services.push(service.name);
      }
      discoverService = {
        includeServices: services,
      };
    }
    if (this.portChecked.length > 0) {
      discoverPort = {
        firstScanRange: this.startPort,
        lastScanRange: this.endPort,
        includeTCP: this.tcpChecked,
        includeUDP: this.udpChecked,
        excludePorts: null,
        discoverService: discoverService
      };
    }
    const discoverZone: DiscoverZone = {
      discoverHost: {
        firstScanRangev4: this.startIP,
        lastScanRangev4: this.endIP,
        discoverPort: discoverPort,
      },
    };


    console.log(discoverZone);

    // console.log('start discovery - ' + this.probe.probeKey);
    this.discoverstore.dispatch(new DiscoverStore.DiscoverZone(
      { probeID: this.probe.probeKey, discoverZone: discoverZone }));

    this.started = true;
  }

  checkDiscoveryResult(node) {

    node.toggleActivated(true);

    if (node.isActive) {
      if (node.data.obj !== undefined) {
        node.data.obj.target = true;
      }
    } else {
      if (node.data.obj !== undefined) {
        node.data.obj.target = false;
      }
    }

    console.log(this.zones);

  }

  convertMapToList(map: Map<any, any>): Array<any> {

    if (undefined === map || null === map || map.size < 0) {
      return null;
    }

    const retArr = new Array();

    map.forEach((v: any, k: any) => {
      retArr.push(v);
    });

    return retArr;
  }


  discoveryResultSave() {
    // console.log(this.checkedSet);

    // send discovery save  this.zones;

    // this.registStore.dispatch(new DiscoverStore.DiscoverZone(
    //   {probeID: '52abd6fd57e511e7ac52080027658d13', discoveryZone: discoveryZone}));

    // console.log(this.zones);
    // isTarget Check


    for (const sn of this.selectedNodes) {
      if (sn.obj !== undefined && sn.obj !== null) {
        if (sn.obj.target !== undefined && sn.obj.target !== null) {
          sn.obj.target = true;
        }
      }
    }

    this.zones.forEach((zone: Zone, key: string) => {
      if (zone.hosts !== undefined && zone.hosts !== null && zone.hosts.size > 0) {
        // FIXME: getHosts
        const hosts: Host[] = [];
        zone.hosts.forEach((h: Host, hKey: string) => {

          h.zone = null;
          if (h.ports !== undefined && h.ports !== null) {
            h.portList = [];
            h.ports.forEach((p: Port, pKey: number) => {

              p.host = null;
              if (p.services !== undefined && p.services !== null) {
                p.serviceList = [];

                p.services.forEach((s: Service, sKey: string) => {
                  s.port = null;

                  p.serviceList.push(s);
                });

              }

              h.portList.push(p);
            });
          }

          hosts.push(h);
        });

        if (hosts.length > 0) {
          const sd: any = { hosts: hosts, probe: { id: 1 } };
          console.log(JSON.stringify(sd));
          console.log('--------');
          this.registStore.dispatch(new RegistStore.DiscoverySaveAllTarget(sd));
        }

      }
    });
  }

  handleClick(event) {
    // console.log(this.filesTree4);

    this.checkTarget(this.selectedDiscoveryResult);

    console.log(this.testObj);

  }

  checkTarget(treeList: any[]) {

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

    for (let i = 0; i < treeList.length; ++i) {
      treeList[i].obj.target = true;

      this.checkTarget(treeList[i].children);
    }

  }

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

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

    // console.log('convertTreeViewZone');
    const treeNodes: any[] = [];

    zones.forEach((value: Zone, key: string, map) => {
      if (this.isZone(value)) {
        return;
      }
      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;
  }

}


const testDiscovery: any[] = [
  {
    id: 0,
    ip: '192.168.1.254',
    mac: '64:e5:99:63:e7:80',
    os: null,
    discoveredDate: -62135596800000,
    target: false,
    zone: null,
    ports: [
      {
        id: 0,
        portType: 'UDP',
        portNumber: 53,
        discoveredDate: -62135596800000,
        host: null,
        services: [
          {
            id: 0,
            cryptoType: null,
            serviceName: 'DNS',
            discoveredDate: -62135596800000,
            port: null,
            target: false
          }
        ]
      }
    ]
  },
  {
    id: 0,
    ip: '192.168.1.99',
    mac: '00:25:b3:fa:ca:9b',
    os: null,
    discoveredDate: -62135596800000,
    target: false,
    zone: null,
    ports: [
      {
        id: 0,
        portType: 'UDP',
        portNumber: 161,
        discoveredDate: -62135596800000,
        host: null,
        services: [
          {
            id: 0,
            cryptoType: null,
            serviceName: 'SNMP_V2',
            discoveredDate: -62135596800000,
            port: null,
            target: false
          }
        ]
      },
      {
        id: 0,
        portType: 'TCP',
        portNumber: 7,
        discoveredDate: -62135596800000,
        host: null,
        services: null
      }
    ]
  },
  {
    id: 0,
    ip: '192.168.1.206',
    mac: '30:9c:23:15:a3:09',
    os: null,
    discoveredDate: -62135596800000,
    target: false,
    zone: null,
    ports: null
  },
  {
    id: 0,
    ip: '192.168.1.50',
    mac: '6c:f0:49:7a:60:68',
    os: null,
    discoveredDate: -62135596800000,
    target: false,
    zone: null,
    ports: [
      {
        id: 0,
        portType: 'TCP',
        portNumber: 22,
        discoveredDate: -62135596800000,
        host: null,
        services: [
          {
            id: 0,
            cryptoType: 'TCP',
            serviceName: 'SSH',
            discoveredDate: -62135596800000,
            port: null,
            target: false
          }
        ]
      }
    ]
  },
  {
    id: 0,
    ip: '192.168.1.15',
    mac: '00:19:b9:35:8e:a6',
    os: null,
    discoveredDate: -62135596800000,
    target: false,
    zone: null,
    ports: [
      {
        id: 0,
        portType: 'TCP',
        portNumber: 22,
        discoveredDate: -62135596800000,
        host: null,
        services: null
      },
      {
        id: 0,
        portType: 'TCP',
        portNumber: 25,
        discoveredDate: -62135596800000,
        host: null,
        services: null
      }
    ]
  },
  {
    id: 0,
    ip: '192.168.1.100',
    mac: '00:17:08:8d:cf:f7',
    os: null,
    discoveredDate: -62135596800000,
    target: false,
    zone: null,
    ports: [
      {
        id: 0,
        portType: 'UDP',
        portNumber: 161,
        discoveredDate: -62135596800000,
        host: null,
        services: [
          {
            id: 0,
            cryptoType: null,
            serviceName: 'SNMP_V2',
            discoveredDate: -62135596800000,
            port: null,
            target: false
          }
        ]
      },
      {
        id: 0,
        portType: 'TCP',
        portNumber: 23,
        discoveredDate: -62135596800000,
        host: null,
        services: null
      },
      {
        id: 0,
        portType: 'TCP',
        portNumber: 21,
        discoveredDate: -62135596800000,
        host: null,
        services: null
      }
    ]
  },
  {
    id: 0,
    ip: '192.168.1.16',
    mac: '00:19:b9:19:7e:c7',
    os: null,
    discoveredDate: -62135596800000,
    target: false,
    zone: null,
    ports: [
      {
        id: 0,
        portType: 'TCP',
        portNumber: 22,
        discoveredDate: -62135596800000,
        host: null,
        services: null
      }
    ]
  },
  {
    id: 0,
    ip: '192.168.1.106',
    mac: '44:8a:5b:f1:3a:7d',
    os: null,
    discoveredDate: -62135596800000,
    target: false,
    zone: null,
    ports: [
      {
        id: 0,
        portType: 'UDP',
        portNumber: 161,
        discoveredDate: -62135596800000,
        host: null,
        services: [
          {
            id: 0,
            cryptoType: null,
            serviceName: 'SNMP_V2',
            discoveredDate: -62135596800000,
            port: null,
            target: false
          }
        ]
      },
      {
        id: 0,
        portType: 'TCP',
        portNumber: 21,
        discoveredDate: -62135596800000,
        host: null,
        services: null
      }
    ]
  },
  {
    id: 0,
    ip: '192.168.1.101',
    mac: '44:8a:5b:f1:f1:f3',
    os: null,
    discoveredDate: -62135596800000,
    target: false,
    zone: null,
    ports: null
  },
  {
    id: 0,
    ip: '192.168.1.102',
    mac: '44:8a:5b:f1:f2:d3',
    os: null,
    discoveredDate: -62135596800000,
    target: false,
    zone: null,
    ports: null
  },
  {
    id: 0,
    ip: '192.168.1.205',
    mac: '40:98:ad:7b:d0:43',
    os: null,
    discoveredDate: -62135596800000,
    target: false,
    zone: null,
    ports: null
  },
  {
    id: 0,
    ip: '192.168.1.103',
    mac: '44:8a:5b:44:8c:e8',
    os: null,
    discoveredDate: -62135596800000,
    target: false,
    zone: null,
    ports: [
      {
        id: 0,
        portType: 'TCP',
        portNumber: 21,
        discoveredDate: -62135596800000,
        host: null,
        services: null
      }
    ]
  },
  {
    id: 0,
    ip: '192.168.1.10',
    mac: 'd0:50:99:97:5d:99',
    os: null,
    discoveredDate: -62135596800000,
    target: false,
    zone: null,
    ports: [
      {
        id: 0,
        portType: 'TCP',
        portNumber: 22,
        discoveredDate: -62135596800000,
        host: null,
        services: null
      }
    ]
  },
  {
    id: 0,
    ip: '192.168.1.203',
    mac: 'a8:e5:39:5b:c9:62',
    os: null,
    discoveredDate: -62135596800000,
    target: false,
    zone: null,
    ports: null
  }
];

