<!--
@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-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 src="../../types/polymer-behaviors.js"></script>

<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_USER_DASHBOARD: 'GO_TO_USER_DASHBOARD',
    GO_TO_OPENED_CHANGES: 'GO_TO_OPENED_CHANGES',
    GO_TO_MERGED_CHANGES: 'GO_TO_MERGED_CHANGES',
    GO_TO_ABANDONED_CHANGES: 'GO_TO_ABANDONED_CHANGES',
    GO_TO_WATCHED_CHANGES: 'GO_TO_WATCHED_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',
    VISIBLE_LINE: 'VISIBLE_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',
    EMOJI_DROPDOWN: 'EMOJI_DROPDOWN',
    TOGGLE_BLAME: 'TOGGLE_BLAME',
  };

  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_USER_DASHBOARD, ShortcutSection.EVERYWHERE,
      'Go to User Dashboard');
  _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.GO_TO_WATCHED_CHANGES, ShortcutSection.EVERYWHERE,
      'Go to Watched 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.VISIBLE_LINE, ShortcutSection.DIFFS,
      'Move cursor to currently visible code');
  _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.TOGGLE_BLAME, ShortcutSection.DIFFS, 'Toggle blame');

  _describe(Shortcut.NEXT_FILE, ShortcutSection.NAVIGATION, 'Go to next file');
  _describe(Shortcut.PREV_FILE, ShortcutSection.NAVIGATION,
      'Go to previous file');
  _describe(Shortcut.NEXT_FILE_WITH_COMMENTS, ShortcutSection.NAVIGATION,
      'Go to next file that has comments');
  _describe(Shortcut.PREV_FILE_WITH_COMMENTS, ShortcutSection.NAVIGATION,
      'Go to previous file that has comments');
  _describe(Shortcut.OPEN_FIRST_FILE, ShortcutSection.NAVIGATION,
      'Go to first file');
  _describe(Shortcut.OPEN_LAST_FILE, ShortcutSection.NAVIGATION,
      'Go to 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');
  _describe(Shortcut.EMOJI_DROPDOWN, ShortcutSection.REPLY_DIALOG,
      'Emoji dropdown');

  // 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);
    }

    getDescription(section, shortcutName) {
      const binding =
          _help.get(section).find(binding => binding.shortcut == shortcutName);
      return binding ? binding.text : '';
    }

    getShortcut(shortcutName) {
      const binding = this.bindings.get(shortcutName);
      return binding ? this.describeBinding(binding) : '';
    }

    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) {
      if (binding.length === 1) {
        return [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 Gerrit.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,
      // eslint-disable-next-line object-shorthand
      ShortcutSection: ShortcutSection,

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

        this.fire('shortcut-triggered', {
          event: e,
          goKey: this._inGoKeyMode(),
        });
        return false;
      },

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

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

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

      createTitle(shortcutName, section) {
        const desc = shortcutManager.getDescription(section, shortcutName);
        const shortcut = shortcutManager.getShortcut(shortcutName);
        return (desc && shortcut) ? `${desc} (shortcut: ${shortcut})` : '';
      },

      _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);
        }
      },

      /** @override */
      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');
          });
        }
      },

      /** @override */
      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;
      },

      _inGoKeyMode() {
        return this._shortcut_go_key_last_pressed &&
            (Date.now() - this._shortcut_go_key_last_pressed <=
                GO_KEY_TIMEOUT_MS);
      },

      _handleGoAction(e) {
        if (!this._inGoKeyMode() ||
            !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);
    },
  };

  // eslint-disable-next-line no-unused-vars
  function defineEmptyMixin() {
    // This is a temporary function.
    // Polymer linter doesn't process correctly the following code:
    // class MyElement extends Polymer.mixinBehaviors([legacyBehaviors], ...) {...}
    // To workaround this issue, the mock mixin is declared in this method.
    // In the following changes, legacy behaviors will be converted to mixins.

    /**
     * @polymer
     * @mixinFunction
     */
    Gerrit.KeyboardShortcutMixin = base =>
      class extends base {
        get Shortcut() { return undefined; }

        get ShortcutSection() { return undefined; }

        createTitle(shortcutName, section) {}
      };
  }
})(window);
</script>
