/*
 * 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 { Injectable } from '@angular/core';
import * as d3 from 'd3';
import { LogService } from '../log.service';
import { FnService } from '../util/fn.service';
import { LionService } from './lion.service';
import { NavService } from '../nav/nav.service';

export interface KeyHandler {
    globalKeys: Object;
    maskedKeys: Object;
    dialogKeys: Object;
    viewKeys: any;
    viewFn: any;
    viewGestures: string[][];
}

export enum KeysToken {
    KEYEV = 'keyev'
}

/**
 * ONOS GUI -- Keys Service Module.
 */
@Injectable({
    providedIn: 'root',
})
export class KeysService {
    enabled: boolean = true;
    globalEnabled: boolean = true;
    keyHandler: KeyHandler = <KeyHandler>{
        globalKeys: {},
        maskedKeys: {},
        dialogKeys: {},
        viewKeys: {},
        viewFn: null,
        viewGestures: [],
    };

    seq: any = {};
    matching: boolean = false;
    matched: string = '';
    lookup: any;
    textFieldDoesNotBlock: any = {
        enter: 1,
        esc: 1,
    };
    quickHelpShown: boolean = false;

    constructor(
        protected log: LogService,
        protected fs: FnService,
        protected ls: LionService,
        protected ns: NavService
    ) {
        this.log.debug('KeyService constructed');
    }

    installOn(elem) {
        this.log.debug('Installing keys handler');
        elem.on('keydown', () => { this.keyIn(); });
        this.setupGlobalKeys();
    }

    keyBindings(x) {
        if (x === undefined) {
            return this.getKeyBindings();
        } else {
            this.setKeyBindings(x);
        }
    }

    unbindKeys() {
        this.keyHandler.viewKeys = {};
        this.keyHandler.viewFn = null;
        this.keyHandler.viewGestures = [];
    }

    dialogKeys(x) {
        if (x === undefined) {
            this.unbindDialogKeys();
        } else {
            this.bindDialogKeys(x);
        }
    }

    addSeq(word, data) {
        this.fs.addToTrie(this.seq, word, data);
    }

    remSeq(word) {
        this.fs.removeFromTrie(this.seq, word);
    }

    gestureNotes(g?) {
        if (g === undefined) {
            return this.keyHandler.viewGestures;
        } else {
            this.keyHandler.viewGestures = this.fs.isA(g) || [];
        }
    }

    enableKeys(b) {
        this.enabled = b;
    }

    enableGlobalKeys(b) {
        this.globalEnabled = b;
    }

    checkNotGlobal(o) {
        const oops = [];
        if (this.fs.isO(o)) {
            o.forEach((val, key) => {
                if (this.keyHandler.globalKeys[key]) {
                    oops.push(key);
                }
            });
            if (oops.length) {
                this.log.warn('Ignoring reserved global key(s):', oops.join(','));
                oops.forEach((key) => {
                    delete o[key];
                });
            }
        }
    }

    protected matchSeq(key) {
        if (!this.matching && key === 'shift-shift') {
            this.matching = true;
            return true;
        }
        if (this.matching) {
            this.matched += key;
            this.lookup = this.fs.trieLookup(this.seq, this.matched);
            if (this.lookup === -1) {
                return true;
            }
            this.matching = false;
            this.matched = '';
            if (!this.lookup) {
                return;
            }
            // ee.cluck(lookup);
            return true;
        }
    }

    protected whatKey(code: number): string {
        switch (code) {
            case 8: return 'delete';
            case 9: return 'tab';
            case 13: return 'enter';
            case 16: return 'shift';
            case 27: return 'esc';
            case 32: return 'space';
            case 37: return 'leftArrow';
            case 38: return 'upArrow';
            case 39: return 'rightArrow';
            case 40: return 'downArrow';
            case 186: return 'semicolon';
            case 187: return 'equals';
            case 188: return 'comma';
            case 189: return 'dash';
            case 190: return 'dot';
            case 191: return 'slash';
            case 192: return 'backQuote';
            case 219: return 'openBracket';
            case 220: return 'backSlash';
            case 221: return 'closeBracket';
            case 222: return 'quote';
            default:
                if ((code >= 48 && code <= 57) ||
                    (code >= 65 && code <= 90)) {
                    return String.fromCharCode(code);
                } else if (code >= 112 && code <= 123) {
                    return 'F' + (code - 111);
                }
                return null;
        }
    }

    protected textFieldInput() {
        const t = d3.event.target.tagName.toLowerCase();
        return t === 'input' || t === 'textarea';
    }

    protected keyIn() {
        const event = d3.event;
        // d3.events can set the keyCode, but unit tests based on KeyboardEvent
        // cannot set keyCode since the attribute has been deprecated
        const code = event.keyCode ? event.keyCode : event.code;
        let key = this.whatKey(Number.parseInt(code, 10));
        this.log.debug('Key detected', event, key, event.code, event.keyCode);
        const textBlockable = !this.textFieldDoesNotBlock[key];
        const modifiers = [];

        if (event.metaKey) {
            modifiers.push('cmd');
        }
        if (event.altKey) {
            modifiers.push('alt');
        }
        if (event.shiftKey) {
            modifiers.push('shift');
        }

        if (!key) {
            return;
        }

        modifiers.push(key);
        key = modifiers.join('-');

        if (textBlockable && this.textFieldInput()) {
            return;
        }

        const kh: KeyHandler = this.keyHandler;
        const gk = kh.globalKeys[key];
        const gcb = this.fs.isF(gk) || (this.fs.isA(gk) && this.fs.isF(gk[0]));
        const dk = kh.dialogKeys[key];
        const dcb = this.fs.isF(dk);
        const vk = kh.viewKeys[key];
        const kl = this.fs.isF(kh.viewKeys._keyListener);
        const vcb = this.fs.isF(vk) || (this.fs.isA(vk) && this.fs.isF(vk[0])) || this.fs.isF(kh.viewFn);
        const token: KeysToken = KeysToken.KEYEV; // indicate this was a key-pressed event

        event.stopPropagation();

        if (this.enabled) {
            if (this.matchSeq(key)) {
                return;
            }

            // global callback?
            if (gcb && gcb(token, key, code, event)) {
                // if the event was 'handled', we are done
                return;
            }
            // dialog callback?
            if (dcb) {
                dcb(token, key, code, event);
                // assume dialog handled the event
                return;
            }
            // otherwise, let the view callback have a shot
            if (vcb) {
                this.log.debug('Letting view callback have a shot', vcb, token, key, code, event );
                vcb(token, key, code, event);
            }
            if (kl) {
                kl(key);
            }
        }
    }

    // functions to obtain localized strings deferred from the setup of the
    //  global key data structures.
    protected qhlion() {
        return this.ls.bundle('core.fw.QuickHelp');
    }
    protected qhlionShowHide() {
        return this.qhlion()('qh_hint_show_hide_qh');
    }

    protected qhlionHintEsc() {
        return this.qhlion()('qh_hint_esc');
    }

    protected qhlionHintT() {
        return this.qhlion()('qh_hint_t');
    }

    protected setupGlobalKeys() {
        Object.assign(this.keyHandler, {
            globalKeys: {
                backSlash: [(view, key, code, ev) => this.quickHelp(view, key, code, ev), this.qhlionShowHide],
                slash: [(view, key, code, ev) => this.quickHelp(view, key, code, ev), this.qhlionShowHide],
                esc: [(view, key, code, ev) => this.escapeKey(view, key, code, ev), this.qhlionHintEsc],
                T: [(view, key, code, ev) => this.toggleTheme(view, key, code, ev), this.qhlionHintT],
            },
            globalFormat: ['backSlash', 'slash', 'esc', 'T'],

            // Masked keys are global key handlers that always return true.
            // That is, the view will never see the event for that key.
            maskedKeys: {
                slash: 1,
                backSlash: 1,
                T: 1,
            },
        });
    }

    protected quickHelp(view, key, code, ev) {
        if (!this.globalEnabled) {
            return false;
        }
        this.quickHelpShown = !this.quickHelpShown;
        return true;
    }

    // returns true if we 'consumed' the ESC keypress, false otherwise
    protected escapeKey(view, key, code, ev) {
        this.quickHelpShown = false;
        return this.ns.hideNav();
    }

    protected toggleTheme(view, key, code, ev) {
        if (!this.globalEnabled) {
            return false;
        }
        // ts.toggleTheme();
        return true;
    }

    protected filterMaskedKeys(map: any, caller: any, remove: boolean): any[] {
        const masked = [];
        const msgs = [];

        d3.map(map).keys().forEach((key) => {
            if (this.keyHandler.maskedKeys[key]) {
                masked.push(key);
                msgs.push(caller, ': Key "' + key + '" is reserved');
            }
        });

        if (msgs.length) {
            this.log.warn(msgs.join('\n'));
        }

        if (remove) {
            masked.forEach((k) => {
                delete map[k];
            });
        }
        return masked;
    }

    protected unexParam(fname, x) {
        this.log.warn(fname, ': unexpected parameter-- ', x);
    }

    protected setKeyBindings(keyArg) {
        const fname = 'setKeyBindings()';
        const kFunc = this.fs.isF(keyArg);
        const kMap = this.fs.isO(keyArg);

        if (kFunc) {
            // set general key handler callback
            this.keyHandler.viewFn = kFunc;
        } else if (kMap) {
            this.filterMaskedKeys(kMap, fname, true);
            this.keyHandler.viewKeys = kMap;
        } else {
            this.unexParam(fname, keyArg);
        }
    }

    getKeyBindings() {
        const gkeys = d3.map(this.keyHandler.globalKeys).keys();
        const masked = d3.map(this.keyHandler.maskedKeys).keys();
        const vkeys = d3.map(this.keyHandler.viewKeys).keys();
        const vfn = !!this.fs.isF(this.keyHandler.viewFn);

        return {
            globalKeys: gkeys,
            maskedKeys: masked,
            viewKeys: vkeys,
            viewFunction: vfn,
        };
    }

    protected bindDialogKeys(map) {
        const fname = 'bindDialogKeys()';
        const kMap = this.fs.isO(map);

        if (kMap) {
            this.filterMaskedKeys(map, fname, true);
            this.keyHandler.dialogKeys = kMap;
        } else {
            this.unexParam(fname, map);
        }
    }

    protected unbindDialogKeys() {
        this.keyHandler.dialogKeys = {};
    }

}
