
/*
 * Copyright 2017-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 * as $ from 'jquery';
import * as _ from 'lodash';
import {IXosSidePanelService} from '../side-panel/side-panel.service';

export interface IXosKeyboardShortcutService {
  keyMapping: IXosKeyboardShortcutMap;
  registerKeyBinding(binding: IXosKeyboardShortcutBinding, target?: string);
  setup(): void;
}

export interface IXosKeyboardShortcutMap {
  global: IXosKeyboardShortcutBinding[];
  view: IXosKeyboardShortcutBinding[];
}

export interface IXosKeyboardShortcutBinding {
  key: string;
  cb: any;
  modifiers?: string[];
  label?: string;
  description?: string;
  onInput?: boolean;
}

export class XosKeyboardShortcut implements IXosKeyboardShortcutService {
  static $inject = ['$log', '$transitions', 'XosSidePanel'];
  public keyMapping: IXosKeyboardShortcutMap = {
    global: [],
    view: []
  };
  public allowedModifiers: string[] = ['meta', 'alt', 'shift', 'control'];
  public activeModifiers: string[] = [];

  private toggleKeyBindingPanel = (): void => {
    if (!this.isPanelOpen) {
      this.XosSidePanel.injectComponent('xosKeyBindingPanel');
      this.isPanelOpen = true;
    }
    else {
      this.XosSidePanel.removeInjectedComponents();
      this.isPanelOpen = false;
    }
  };

  /* tslint:disable */
  public baseBindings: IXosKeyboardShortcutBinding[] = [
    {
      key: 'slash',
      label: '/',
      description: 'Toggle Shortcut Panel',
      cb: this.toggleKeyBindingPanel,
    },
    {
      key: 'esc',
      label: 'Esc',
      cb: (event) => {
        // NOTE removing focus from input elements on Esc
        event.target.blur();
      },
      onInput: true
    }
  ];
  /* tslint:enable */

  private isPanelOpen: boolean;

  constructor(
    private $log: ng.ILogService,
    $transitions: any,
    private XosSidePanel: IXosSidePanelService
  ) {
    this.keyMapping.global = this.keyMapping.global.concat(this.baseBindings);

    $transitions.onStart({ to: '**' }, (transtion) => {
      // delete view keys before that a new view is loaded
        this.$log.debug(`[XosKeyboardShortcut] Deleting view keys`);
        this.keyMapping.view = [];
    });
  }


  public setup(): void {
    this.$log.info(`[XosKeyboardShortcut] Setup`);
    $('body').on('keydown', (e) => {

      const pressedKey = this.whatKey(e.which);

      if (!pressedKey) {
        return;
      }

      if (this.allowedModifiers.indexOf(e.key) > -1) {
        this.addActiveModifierKey(e.key);
        return;
      }

      // NOTE e.key change if we are using some modifiers (eg: Alt) while getting the value from the keyCode works
      const binding = this.findBindedShortcut(pressedKey);
      if (angular.isDefined(binding) && angular.isFunction(binding.cb)) {
        // NOTE disable binding if they come from an input or textarea
        // if not different specified
        const t = e.target.tagName.toLowerCase();
        if ((t === 'input' || t === 'textarea') && !binding.onInput) {
          return;
        }
        binding.cb(e);
        e.preventDefault();
      }
    });

    $('body').on('keyup', (e) => {
      if (this.allowedModifiers.indexOf(e.key) > -1) {
        this.removeActiveModifierKey(e.key);
        return;
      }
    });
  }

  public registerKeyBinding(binding: IXosKeyboardShortcutBinding, target: string = 'view'): void {

    if (target !== 'global' && target !== 'view') {
      throw new Error('[XosKeyboardShortcut] A shortcut can be registered with scope "global" or "view" only');
    }

    binding.key = binding.key.toLowerCase();
    if (_.find(this.keyMapping.global, {key: binding.key}) || _.find(this.keyMapping.view, {key: binding.key})) {
      this.$log.warn(`[XosKeyboardShortcut] A shortcut for key "${binding.key}" has already been registered`);
      return;
    }

    this.$log.debug(`[XosKeyboardShortcut] Registering binding for key: ${binding.key}`);
    this.keyMapping[target].push(binding);
  }

  private addActiveModifierKey(key: string) {
    if (this.activeModifiers.indexOf(key) === -1) {
      this.activeModifiers.push(key);
    }
  }

  private removeActiveModifierKey(key: string) {
    _.remove(this.activeModifiers, k => k === key);
  }

  private findBindedShortcut(key: string): IXosKeyboardShortcutBinding {
    const globalTargets =  _.filter(this.keyMapping.global, {key: key.toLowerCase()});

    const localTargets = _.filter(this.keyMapping.view, {key: key.toLowerCase()});

    let targets = globalTargets.concat(localTargets);

    if (targets.length === 0) {
      return;
    }

    // NOTE remove targets that does not match modifiers
    targets = _.filter(targets, (t: IXosKeyboardShortcutBinding) => {
      if (this.activeModifiers.length === 0) {
        return true;
      }
      else if (t.modifiers && _.difference(t.modifiers, this.activeModifiers).length === 0) {
        return true;
      }
      return false;
    });

    return targets[0];
  }

  private whatKey(code: number) {
    switch (code) {
      case 8: return 'delete';
      case 9: return 'tab';
      case 13: return 'enter';
      case 16: return 'shift';
      case 17: return 'control';
      case 18: return 'alt';
      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 91: return 'meta';
      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;
  }
}

}
