<!--
@license
Copyright (C) 2016 The Android Open Source Project

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.
-->

<!--

How to Add a Keyboard Shortcut
==============================

A keyboard shortcut is composed of the following parts:

  1. A semantic identifier (e.g. OPEN_CHANGE, NEXT_PAGE)
  2. Documentation for the keyboard shortcut help dialog
  3. A binding between key combos and the semantic identifier
  4. A binding between the semantic identifier and a listener

Parts (1) and (2) for all shortcuts are defined in this file. The semantic
identifier is declared in the Shortcut enum near the head of this script:

  const Shortcut = {
    // ...
    TOGGLE_LEFT_PANE: 'TOGGLE_LEFT_PANE',
    // ...
  };

Immediately following the Shortcut enum definition, there is a _describe
function defined which is then invoked many times to populate the help dialog.
Add a new invocation here to document the shortcut:

  _describe(Shortcut.TOGGLE_LEFT_PANE, ShortcutSection.DIFFS,
      'Hide/show left diff');

When an attached view binds one or more key combos to this shortcut, the help
dialog will display this text in the given section (in this case, "Diffs"). See
the ShortcutSection enum immediately below for the list of supported sections.

Part (3), the actual key bindings, are declared by gr-app. In the future, this
system may be expanded to allow key binding customizations by plugins or user
preferences. Key bindings are defined in the following forms:

  // Ordinary shortcut with a single binding.
  this.bindShortcut(
      this.Shortcut.TOGGLE_LEFT_PANE, 'shift+a');

  // Ordinary shortcut with multiple bindings.
  this.bindShortcut(
      this.Shortcut.CURSOR_NEXT_FILE, 'j', 'down');

  // A "go-key" keyboard shortcut, which is combined with a previously and
  // continuously pressed "go" key (the go-key is hard-coded as 'g').
  this.bindShortcut(
      this.Shortcut.GO_TO_OPENED_CHANGES, this.GO_KEY, 'o');

  // A "doc-only" keyboard shortcut. This declares the key-binding for help
  // dialog purposes, but doesn't actually implement the binding. It is up
  // to some element to implement this binding using iron-a11y-keys-behavior's
  // keyBindings property.
  this.bindShortcut(
      this.Shortcut.EXPAND_ALL_COMMENT_THREADS, this.DOC_ONLY, 'e');

Part (4), the listener definitions, are declared by the view or element that
implements the shortcut behavior. This is done by implementing a method named
keyboardShortcuts() in an element that mixes in this behavior, returning an
object that maps semantic identifiers (as property names) to listener method
names, like this:

  keyboardShortcuts() {
    return {
      [this.Shortcut.TOGGLE_LEFT_PANE]: '_handleToggleLeftPane',
    };
  },

You can implement key bindings in an element that is hosted by a view IF that
element is always attached exactly once under that view (e.g. the search bar in
gr-app). When that is not the case, you will have to define a doc-only binding
in gr-app, declare the shortcut in the view that hosts the element, and use
iron-a11y-keys-behavior's keyBindings attribute to implement the binding in the
element. An example of this is in comment threads. A diff view supports actions
on comment threads, but there may be zero or many comment threads attached at
any given point. So the shortcut is declared as doc-only by the diff view and
by gr-app, and actually implemented by gr-diff-comment-thread.

NOTE: doc-only shortcuts will not be customizable in the same way that other
shortcuts are.
-->
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">

<script>
(function(window) {
  'use strict';

  const DOC_ONLY = 'DOC_ONLY';
  const GO_KEY = 'GO_KEY';

  // The maximum age of a keydown event to be used in a jump navigation. This
  // is only for cases when the keyup event is lost.
  const GO_KEY_TIMEOUT_MS = 1000;

  const ShortcutSection = {
    ACTIONS: 'Actions',
    DIFFS: 'Diffs',
    EVERYWHERE: 'Everywhere',
    FILE_LIST: 'File list',
    NAVIGATION: 'Navigation',
    REPLY_DIALOG: 'Reply dialog',
  };

  const Shortcut = {
    OPEN_SHORTCUT_HELP_DIALOG: 'OPEN_SHORTCUT_HELP_DIALOG',
    GO_TO_OPENED_CHANGES: 'GO_TO_OPENED_CHANGES',
    GO_TO_MERGED_CHANGES: 'GO_TO_MERGED_CHANGES',
    GO_TO_ABANDONED_CHANGES: 'GO_TO_ABANDONED_CHANGES',

    CURSOR_NEXT_CHANGE: 'CURSOR_NEXT_CHANGE',
    CURSOR_PREV_CHANGE: 'CURSOR_PREV_CHANGE',
    OPEN_CHANGE: 'OPEN_CHANGE',
    NEXT_PAGE: 'NEXT_PAGE',
    PREV_PAGE: 'PREV_PAGE',
    TOGGLE_CHANGE_REVIEWED: 'TOGGLE_CHANGE_REVIEWED',
    TOGGLE_CHANGE_STAR: 'TOGGLE_CHANGE_STAR',
    REFRESH_CHANGE_LIST: 'REFRESH_CHANGE_LIST',

    OPEN_REPLY_DIALOG: 'OPEN_REPLY_DIALOG',
    OPEN_DOWNLOAD_DIALOG: 'OPEN_DOWNLOAD_DIALOG',
    EXPAND_ALL_MESSAGES: 'EXPAND_ALL_MESSAGES',
    COLLAPSE_ALL_MESSAGES: 'COLLAPSE_ALL_MESSAGES',
    UP_TO_DASHBOARD: 'UP_TO_DASHBOARD',
    UP_TO_CHANGE: 'UP_TO_CHANGE',
    TOGGLE_DIFF_MODE: 'TOGGLE_DIFF_MODE',
    REFRESH_CHANGE: 'REFRESH_CHANGE',
    EDIT_TOPIC: 'EDIT_TOPIC',

    NEXT_LINE: 'NEXT_LINE',
    PREV_LINE: 'PREV_LINE',
    NEXT_CHUNK: 'NEXT_CHUNK',
    PREV_CHUNK: 'PREV_CHUNK',
    EXPAND_ALL_DIFF_CONTEXT: 'EXPAND_ALL_DIFF_CONTEXT',
    NEXT_COMMENT_THREAD: 'NEXT_COMMENT_THREAD',
    PREV_COMMENT_THREAD: 'PREV_COMMENT_THREAD',
    EXPAND_ALL_COMMENT_THREADS: 'EXPAND_ALL_COMMENT_THREADS',
    COLLAPSE_ALL_COMMENT_THREADS: 'COLLAPSE_ALL_COMMENT_THREADS',
    LEFT_PANE: 'LEFT_PANE',
    RIGHT_PANE: 'RIGHT_PANE',
    TOGGLE_LEFT_PANE: 'TOGGLE_LEFT_PANE',
    NEW_COMMENT: 'NEW_COMMENT',
    SAVE_COMMENT: 'SAVE_COMMENT',
    OPEN_DIFF_PREFS: 'OPEN_DIFF_PREFS',
    TOGGLE_DIFF_REVIEWED: 'TOGGLE_DIFF_REVIEWED',

    NEXT_FILE: 'NEXT_FILE',
    PREV_FILE: 'PREV_FILE',
    NEXT_FILE_WITH_COMMENTS: 'NEXT_FILE_WITH_COMMENTS',
    PREV_FILE_WITH_COMMENTS: 'PREV_FILE_WITH_COMMENTS',
    NEXT_UNREVIEWED_FILE: 'NEXT_UNREVIEWED_FILE',
    CURSOR_NEXT_FILE: 'CURSOR_NEXT_FILE',
    CURSOR_PREV_FILE: 'CURSOR_PREV_FILE',
    OPEN_FILE: 'OPEN_FILE',
    TOGGLE_FILE_REVIEWED: 'TOGGLE_FILE_REVIEWED',
    TOGGLE_ALL_INLINE_DIFFS: 'TOGGLE_ALL_INLINE_DIFFS',
    TOGGLE_INLINE_DIFF: 'TOGGLE_INLINE_DIFF',

    OPEN_FIRST_FILE: 'OPEN_FIRST_FILE',
    OPEN_LAST_FILE: 'OPEN_LAST_FILE',

    SEARCH: 'SEARCH',
    SEND_REPLY: 'SEND_REPLY',
  };

  const _help = new Map();

  function _describe(shortcut, section, text) {
    if (!_help.has(section)) {
      _help.set(section, []);
    }
    _help.get(section).push({shortcut, text});
  }

  _describe(Shortcut.SEARCH, ShortcutSection.EVERYWHERE, 'Search');
  _describe(Shortcut.OPEN_SHORTCUT_HELP_DIALOG, ShortcutSection.EVERYWHERE,
      'Show this dialog');
  _describe(Shortcut.GO_TO_OPENED_CHANGES, ShortcutSection.EVERYWHERE,
      'Go to Opened Changes');
  _describe(Shortcut.GO_TO_MERGED_CHANGES, ShortcutSection.EVERYWHERE,
      'Go to Merged Changes');
  _describe(Shortcut.GO_TO_ABANDONED_CHANGES, ShortcutSection.EVERYWHERE,
      'Go to Abandoned Changes');

  _describe(Shortcut.CURSOR_NEXT_CHANGE, ShortcutSection.ACTIONS,
      'Select next change');
  _describe(Shortcut.CURSOR_PREV_CHANGE, ShortcutSection.ACTIONS,
      'Select previous change');
  _describe(Shortcut.OPEN_CHANGE, ShortcutSection.ACTIONS,
      'Show selected change');
  _describe(Shortcut.NEXT_PAGE, ShortcutSection.ACTIONS, 'Go to next page');
  _describe(Shortcut.PREV_PAGE, ShortcutSection.ACTIONS, 'Go to previous page');
  _describe(Shortcut.OPEN_REPLY_DIALOG, ShortcutSection.ACTIONS,
      'Open reply dialog to publish comments and add reviewers');
  _describe(Shortcut.OPEN_DOWNLOAD_DIALOG, ShortcutSection.ACTIONS,
      'Open download overlay');
  _describe(Shortcut.EXPAND_ALL_MESSAGES, ShortcutSection.ACTIONS,
      'Expand all messages');
  _describe(Shortcut.COLLAPSE_ALL_MESSAGES, ShortcutSection.ACTIONS,
      'Collapse all messages');
  _describe(Shortcut.REFRESH_CHANGE, ShortcutSection.ACTIONS,
      'Reload the change at the latest patch');
  _describe(Shortcut.TOGGLE_CHANGE_REVIEWED, ShortcutSection.ACTIONS,
      'Mark/unmark change as reviewed');
  _describe(Shortcut.TOGGLE_FILE_REVIEWED, ShortcutSection.ACTIONS,
      'Toggle review flag on selected file');
  _describe(Shortcut.REFRESH_CHANGE_LIST, ShortcutSection.ACTIONS,
      'Refresh list of changes');
  _describe(Shortcut.TOGGLE_CHANGE_STAR, ShortcutSection.ACTIONS,
      'Star/unstar change');
  _describe(Shortcut.EDIT_TOPIC, ShortcutSection.ACTIONS,
      'Add a change topic');

  _describe(Shortcut.NEXT_LINE, ShortcutSection.DIFFS, 'Go to next line');
  _describe(Shortcut.PREV_LINE, ShortcutSection.DIFFS, 'Go to previous line');
  _describe(Shortcut.NEXT_CHUNK, ShortcutSection.DIFFS,
      'Go to next diff chunk');
  _describe(Shortcut.PREV_CHUNK, ShortcutSection.DIFFS,
      'Go to previous diff chunk');
  _describe(Shortcut.EXPAND_ALL_DIFF_CONTEXT, ShortcutSection.DIFFS,
      'Expand all diff context');
  _describe(Shortcut.NEXT_COMMENT_THREAD, ShortcutSection.DIFFS,
      'Go to next comment thread');
  _describe(Shortcut.PREV_COMMENT_THREAD, ShortcutSection.DIFFS,
      'Go to previous comment thread');
  _describe(Shortcut.EXPAND_ALL_COMMENT_THREADS, ShortcutSection.DIFFS,
      'Expand all comment threads');
  _describe(Shortcut.COLLAPSE_ALL_COMMENT_THREADS, ShortcutSection.DIFFS,
      'Collapse all comment threads');
  _describe(Shortcut.LEFT_PANE, ShortcutSection.DIFFS, 'Select left pane');
  _describe(Shortcut.RIGHT_PANE, ShortcutSection.DIFFS, 'Select right pane');
  _describe(Shortcut.TOGGLE_LEFT_PANE, ShortcutSection.DIFFS,
      'Hide/show left diff');
  _describe(Shortcut.NEW_COMMENT, ShortcutSection.DIFFS, 'Draft new comment');
  _describe(Shortcut.SAVE_COMMENT, ShortcutSection.DIFFS, 'Save comment');
  _describe(Shortcut.OPEN_DIFF_PREFS, ShortcutSection.DIFFS,
      'Show diff preferences');
  _describe(Shortcut.TOGGLE_DIFF_REVIEWED, ShortcutSection.DIFFS,
      'Mark/unmark file as reviewed');
  _describe(Shortcut.TOGGLE_DIFF_MODE, ShortcutSection.DIFFS,
      'Toggle unified/side-by-side diff');
  _describe(Shortcut.NEXT_UNREVIEWED_FILE, ShortcutSection.DIFFS,
      'Mark file as reviewed and go to next unreviewed file');

  _describe(Shortcut.NEXT_FILE, ShortcutSection.NAVIGATION, 'Select next file');
  _describe(Shortcut.PREV_FILE, ShortcutSection.NAVIGATION,
      'Select previous file');
  _describe(Shortcut.NEXT_FILE_WITH_COMMENTS, ShortcutSection.NAVIGATION,
      'Select next file that has comments');
  _describe(Shortcut.PREV_FILE_WITH_COMMENTS, ShortcutSection.NAVIGATION,
      'Select previous file that has comments');
  _describe(Shortcut.OPEN_FIRST_FILE, ShortcutSection.NAVIGATION,
      'Show first file');
  _describe(Shortcut.OPEN_LAST_FILE, ShortcutSection.NAVIGATION,
      'Show last file');
  _describe(Shortcut.UP_TO_DASHBOARD, ShortcutSection.NAVIGATION,
      'Up to dashboard');
  _describe(Shortcut.UP_TO_CHANGE, ShortcutSection.NAVIGATION, 'Up to change');

  _describe(Shortcut.CURSOR_NEXT_FILE, ShortcutSection.FILE_LIST,
      'Select next file');
  _describe(Shortcut.CURSOR_PREV_FILE, ShortcutSection.FILE_LIST,
      'Select previous file');
  _describe(Shortcut.OPEN_FILE, ShortcutSection.FILE_LIST,
      'Go to selected file');
  _describe(Shortcut.TOGGLE_ALL_INLINE_DIFFS, ShortcutSection.FILE_LIST,
      'Show/hide all inline diffs');
  _describe(Shortcut.TOGGLE_INLINE_DIFF, ShortcutSection.FILE_LIST,
      'Show/hide selected inline diff');

  _describe(Shortcut.SEND_REPLY, ShortcutSection.REPLY_DIALOG, 'Send reply');

  // Must be declared outside behavior implementation to be accessed inside
  // behavior functions.

  /** @return {!(Event|PolymerDomApi|PolymerEventApi)} */
  const getKeyboardEvent = function(e) {
    e = Polymer.dom(e.detail ? e.detail.keyboardEvent : e);
    // When e is a keyboardEvent, e.event is not null.
    if (e.event) { e = e.event; }
    return e;
  };

  class ShortcutManager {
    constructor() {
      this.activeHosts = new Map();
      this.bindings = new Map();
      this.listeners = new Set();
    }

    bindShortcut(shortcut, ...bindings) {
      this.bindings.set(shortcut, bindings);
    }

    getBindingsForShortcut(shortcut) {
      return this.bindings.get(shortcut);
    }

    attachHost(host) {
      if (!host.keyboardShortcuts) { return; }
      const shortcuts = host.keyboardShortcuts();
      this.activeHosts.set(host, new Map(Object.entries(shortcuts)));
      this.notifyListeners();
      return shortcuts;
    }

    detachHost(host) {
      if (this.activeHosts.delete(host)) {
        this.notifyListeners();
        return true;
      }
      return false;
    }

    addListener(listener) {
      this.listeners.add(listener);
      listener(this.directoryView());
    }

    removeListener(listener) {
      return this.listeners.delete(listener);
    }

    activeShortcutsBySection() {
      const activeShortcuts = new Set();
      this.activeHosts.forEach(shortcuts => {
        shortcuts.forEach((_, shortcut) => activeShortcuts.add(shortcut));
      });

      const activeShortcutsBySection = new Map();
      _help.forEach((shortcutList, section) => {
        shortcutList.forEach(shortcutHelp => {
          if (activeShortcuts.has(shortcutHelp.shortcut)) {
            if (!activeShortcutsBySection.has(section)) {
              activeShortcutsBySection.set(section, []);
            }
            activeShortcutsBySection.get(section).push(shortcutHelp);
          }
        });
      });
      return activeShortcutsBySection;
    }

    directoryView() {
      const view = new Map();
      this.activeShortcutsBySection().forEach((shortcutHelps, section) => {
        const sectionView = [];
        shortcutHelps.forEach(shortcutHelp => {
          const bindingDesc = this.describeBindings(shortcutHelp.shortcut);
          if (!bindingDesc) { return; }
          this.distributeBindingDesc(bindingDesc).forEach(bindingDesc => {
            sectionView.push({
              binding: bindingDesc,
              text: shortcutHelp.text,
            });
          });
        });
        view.set(section, sectionView);
      });
      return view;
    }

    distributeBindingDesc(bindingDesc) {
      if (bindingDesc.length === 1 ||
          this.comboSetDisplayWidth(bindingDesc) < 21) {
        return [bindingDesc];
      }
      // Find the largest prefix of bindings that is under the
      // size threshold.
      const head = [bindingDesc[0]];
      for (let i = 1; i < bindingDesc.length; i++) {
        head.push(bindingDesc[i]);
        if (this.comboSetDisplayWidth(head) >= 21) {
          head.pop();
          return [head].concat(
              this.distributeBindingDesc(bindingDesc.slice(i)));
        }
      }
    }

    comboSetDisplayWidth(bindingDesc) {
      const bindingSizer = binding => binding.reduce(
          (acc, key) => acc + key.length, 0);
      // Width is the sum of strings + (n-1) * 2 to account for the word
      // "or" joining them.
      return bindingDesc.reduce(
          (acc, binding) => acc + bindingSizer(binding), 0) +
          2 * (bindingDesc.length - 1);
    }

    describeBindings(shortcut) {
      const bindings = this.bindings.get(shortcut);
      if (!bindings) { return null; }
      if (bindings[0] === GO_KEY) {
        return [['g'].concat(bindings.slice(1))];
      }
      return bindings
          .filter(binding => binding !== DOC_ONLY)
          .map(binding => this.describeBinding(binding));
    }

    describeBinding(binding) {
      return binding.split(':')[0].split('+').map(part => {
        switch (part) {
          case 'shift':
            return 'Shift';
          case 'meta':
            return 'Meta';
          case 'ctrl':
            return 'Ctrl';
          case 'enter':
            return 'Enter';
          case 'up':
            return '↑';
          case 'down':
            return '↓';
          case 'left':
            return '←';
          case 'right':
            return '→';
          default:
            return part;
        }
      });
    }

    notifyListeners() {
      const view = this.directoryView();
      this.listeners.forEach(listener => listener(view));
    }
  }

  const shortcutManager = new ShortcutManager();

  window.Gerrit = window.Gerrit || {};

  /** @polymerBehavior KeyboardShortcutBehavior */
  Gerrit.KeyboardShortcutBehavior = [
    Polymer.IronA11yKeysBehavior,
    {
      // Exports for convenience. Note: Closure compiler crashes when
      // object-shorthand syntax is used here.
      // eslint-disable-next-line object-shorthand
      DOC_ONLY: DOC_ONLY,
      // eslint-disable-next-line object-shorthand
      GO_KEY: GO_KEY,
      // eslint-disable-next-line object-shorthand
      Shortcut: Shortcut,

      properties: {
        _shortcut_go_key_last_pressed: {
          type: Number,
          value: null,
        },

        _shortcut_go_table: {
          type: Array,
          value() { return new Map(); },
        },
      },

      modifierPressed(e) {
        e = getKeyboardEvent(e);
        return e.altKey || e.ctrlKey || e.metaKey || e.shiftKey;
      },

      isModifierPressed(e, modifier) {
        return getKeyboardEvent(e)[modifier];
      },

      shouldSuppressKeyboardShortcut(e) {
        e = getKeyboardEvent(e);
        const tagName = Polymer.dom(e).rootTarget.tagName;
        if (tagName === 'INPUT' || tagName === 'TEXTAREA' ||
            (e.keyCode === 13 && tagName === 'A')) {
          // Suppress shortcuts if the key is 'enter' and target is an anchor.
          return true;
        }
        for (let i = 0; e.path && i < e.path.length; i++) {
          if (e.path[i].tagName === 'GR-OVERLAY') { return true; }
        }
        return false;
      },

      // Alias for getKeyboardEvent.
      /** @return {!(Event|PolymerDomApi|PolymerEventApi)} */
      getKeyboardEvent(e) {
        return getKeyboardEvent(e);
      },

      getRootTarget(e) {
        return Polymer.dom(getKeyboardEvent(e)).rootTarget;
      },

      bindShortcut(shortcut, ...bindings) {
        shortcutManager.bindShortcut(shortcut, ...bindings);
      },

      _addOwnKeyBindings(shortcut, handler) {
        const bindings = shortcutManager.getBindingsForShortcut(shortcut);
        if (!bindings) {
          return;
        }
        if (bindings[0] === DOC_ONLY) {
          return;
        }
        if (bindings[0] === GO_KEY) {
          this._shortcut_go_table.set(bindings[1], handler);
        } else {
          this.addOwnKeyBinding(bindings.join(' '), handler);
        }
      },

      attached() {
        const shortcuts = shortcutManager.attachHost(this);
        if (!shortcuts) { return; }

        for (const key of Object.keys(shortcuts)) {
          this._addOwnKeyBindings(key, shortcuts[key]);
        }

        // If any of the shortcuts utilized GO_KEY, then they are handled
        // directly by this behavior.
        if (this._shortcut_go_table.size > 0) {
          this.addOwnKeyBinding('g:keydown', '_handleGoKeyDown');
          this.addOwnKeyBinding('g:keyup', '_handleGoKeyUp');
          this._shortcut_go_table.forEach((handler, key) => {
            this.addOwnKeyBinding(key, '_handleGoAction');
          });
        }
      },

      detached() {
        if (shortcutManager.detachHost(this)) {
          this.removeOwnKeyBindings();
        }
      },

      keyboardShortcuts() {
        return {};
      },

      addKeyboardShortcutDirectoryListener(listener) {
        shortcutManager.addListener(listener);
      },

      removeKeyboardShortcutDirectoryListener(listener) {
        shortcutManager.removeListener(listener);
      },

      _handleGoKeyDown(e) {
        if (this.modifierPressed(e)) { return; }
        this._shortcut_go_key_last_pressed = Date.now();
      },

      _handleGoKeyUp(e) {
        this._shortcut_go_key_last_pressed = null;
      },

      _handleGoAction(e) {
        if (!this._shortcut_go_key_last_pressed ||
            (Date.now() - this._shortcut_go_key_last_pressed >
                GO_KEY_TIMEOUT_MS) ||
            !this._shortcut_go_table.has(e.detail.key) ||
            this.shouldSuppressKeyboardShortcut(e)) {
          return;
        }
        e.preventDefault();
        const handler = this._shortcut_go_table.get(e.detail.key);
        this[handler](e);
      },
    },
  ];

  Gerrit.KeyboardShortcutBinder = {
    DOC_ONLY,
    GO_KEY,
    Shortcut,
    ShortcutManager,
    ShortcutSection,

    bindShortcut(shortcut, ...bindings) {
      shortcutManager.bindShortcut(shortcut, ...bindings);
    },
  };
})(window);
</script>
