/*
 * Copyright 2018-present Open Networking Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { Component, OnInit, AfterViewInit, OnDestroy } from '@angular/core';
import { Observable, Subscription, fromEvent } from 'rxjs';
import * as d3 from 'd3';
import {
    LionService,
    LogService,
    ThemeService,
    GlyphService,
    WebSocketService,
    WsOptions,
    KeysService
} from 'gui2-fw-lib';
import { OnosService, View } from './onos.service';

// secret sauce
const sauce: string[] = [
    '6:69857666',
    '9:826970',
    '22:8069828667',
    '6:698570688669887967',
    '7:6971806889847186',
    '22:8369867682',
    '13:736583',
    '7:667186698384',
    '1:857780888778876787',
    '20:70717066',
    '24:886774868469',
    '17:7487696973687580739078',
    '14:70777086',
    '17:7287687967',
    '11:65678869706783687184',
    '1:80777778',
    '9:72696982',
    '7:857165828967',
    '11:8867696882678869759071'
    // Add more sauce...
];

function cap(s: string): string {
    return s ? s[0].toUpperCase() + s.slice(1) : s;
}

/**
 * The main ONOS Component - the root of the whole user interface
 */
@Component({
  selector: 'onos-root',
  templateUrl: './onos.component.html',
  styleUrls: ['./onos.component.css', './onos.common.css']
})
export class OnosComponent implements OnInit, AfterViewInit, OnDestroy {
    private quickHelpSub: Subscription;
    private quickHelpHandler: Observable<string>;

    // view ID to help page url map.. injected via the servlet
    viewMap: View[]  = [
        // {INJECTED-VIEW-DATA-START}
        // {INJECTED-VIEW-DATA-END}
    ];

    defaultView = 'topo';
    // TODO Move this to OnosModule - warning servlet will have to be updated too
    viewDependencies: string[] = [];

    constructor (
        private lion: LionService,
        private ts: ThemeService,
        private gs: GlyphService,
        private ks: KeysService,
        public wss: WebSocketService,
        private log: LogService,
        private onos: OnosService
    ) {

// This is not like onos.js of AngularJS 1.x In this new structure modules are
// imported instead in the OnosModule. view dependencies should be there too
//        const moduleDependencies = coreDependencies.concat(this.viewDependencies);

        // Testing of debugging
        log.debug('OnosComponent: testing logger.debug()');
        log.info('OnosComponent: testing logger.info()');
        log.warn('OnosComponent: testing logger.warn()');
        log.error('OnosComponent: testing logger.error()');

        this.wss.createWebSocket(<WsOptions>{ wsport: 8181});

        log.debug('OnosComponent constructed');
    }

    ngOnInit() {
        this.viewMap.forEach(view =>
            this.viewDependencies.push('ov' + cap(view.id)));

        this.onos.viewMap = this.viewMap;

        // TODO: Enable this   this.saucy(this.ee, this.ks);
        this.log.debug('OnosComponent initialized');
    }

    /**
     * Start the listener for keystrokes for QuickHelp
     *
     * This creates an observable that listens to the '/','\' and Esc keystrokes
     * anywhere in the web page - it strips the keyCode out of the keystroke
     * and passes this to another observable that filters only for these keystrokes
     * and finally maps these key code to text literals to drive the
     * quick help feature
     */
    ngAfterViewInit() {
        // const keyStrokeHandler =
        //     fromEvent(document, 'keyup').pipe(map((x: KeyboardEvent) => x.keyCode));
        // this.quickHelpHandler = keyStrokeHandler.pipe(
        //     filter(x => {
        //         return [27, 191, 220].includes(x);
        //     })
        // ).pipe(
        //     map(x => {
        //         let direction;
        //         switch (x) {
        //             case 27:
        //                 direction = 'esc';
        //                 break;
        //             case 191:
        //                 direction = 'fwdslash';
        //                 break;
        //             case 220:
        //                 direction = 'backslash';
        //                 break;
        //             default:
        //                 direction = 'esc';
        //         }
        //         return direction;
        //     })
        // );
        //
        // // TODO: Make a Quick Help component popup
        // this.quickHelpSub = this.quickHelpHandler.subscribe((keyname) => {
        //     this.log.debug('Keystroke', keyname);
        // });
        this.ks.installOn(d3.select('body'));
        this.log.debug('OnosComponent after view initialized');
    }

    ngOnDestroy() {
        if (this.wss.isConnected()) {
            this.log.debug('Stopping Web Socket connection');
            this.wss.closeWebSocket();
        }

        this.quickHelpSub.unsubscribe();
        this.log.debug('OnosComponent destroyed');
    }

    saucy(ee, ks) {
        const map1 = ee.genMap(sauce);
        Object.keys(map1).forEach(function (k) {
            ks.addSeq(k, map1[k]);
        });
    }
}
