/*
 * 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,
    };
    qhs: any; // Quick Help Service ??

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

    bindQhs(_qhs_) {
        this.qhs = _qhs_;
    }

    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));
        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.qhs.showQuickHelp(this.keyHandler);
        return true;
    }

    // returns true if we 'consumed' the ESC keypress, false otherwise
    protected escapeKey(view, key, code, ev) {
        return this.ns.hideNav();
        // TODO - also hide this.qhs.hideQuickHelp();
    }

    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 = {};
    }

}
