/**
 * @license
 * Copyright (C) 2021 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.
 */
import {
  config,
  Shortcut,
  ShortcutHelpItem,
  ShortcutSection,
} from './shortcuts-config';
import {disableShortcuts$} from '../user/user-model';
import {
  ComboKey,
  eventMatchesShortcut,
  isElementTarget,
  Key,
  Modifier,
  Binding,
  shouldSuppress,
} from '../../utils/dom-util';
import {ReportingService} from '../gr-reporting/gr-reporting';

export type SectionView = Array<{binding: string[][]; text: string}>;

export interface ShortcutListener {
  shortcut: Shortcut;
  listener: (e: KeyboardEvent) => void;
}

export function listen(
  shortcut: Shortcut,
  listener: (e: KeyboardEvent) => void
): ShortcutListener {
  return {shortcut, listener};
}

/**
 * The interface for listener for shortcut events.
 */
export type ShortcutViewListener = (
  viewMap?: Map<ShortcutSection, SectionView>
) => void;

function isComboKey(key: string): key is ComboKey {
  return Object.values(ComboKey).includes(key as ComboKey);
}

export const COMBO_TIMEOUT_MS = 1000;

/**
 * Shortcuts service, holds all hosts, bindings and listeners.
 */
export class ShortcutsService {
  /**
   * Keeps track of the components that are currently active such that we can
   * show a shortcut help dialog that only shows the shortcuts that are
   * currently relevant.
   */
  private readonly activeShortcuts = new Map<HTMLElement, Shortcut[]>();

  /**
   * Keeps track of cleanup callbacks (which remove keyboard listeners) that
   * have to be invoked when a component unregisters itself.
   */
  private readonly cleanupsPerHost = new Map<HTMLElement, (() => void)[]>();

  /** Static map built in the constructor by iterating over the config. */
  private readonly bindings = new Map<Shortcut, Binding[]>();

  private readonly listeners = new Set<ShortcutViewListener>();

  /**
   * Stores the timestamp of the last combo key being pressed.
   * This enabled key combinations like 'g+o' where we can check whether 'g' was
   * pressed recently when 'o' is processed. Keys of this map must be items of
   * COMBO_KEYS. Values are Date timestamps in milliseconds.
   */
  private comboKeyLastPressed: {key?: ComboKey; timestampMs?: number} = {};

  /** Keeps track of the corresponding user preference. */
  private shortcutsDisabled = false;

  constructor(readonly reporting?: ReportingService) {
    for (const section of config.keys()) {
      const items = config.get(section) ?? [];
      for (const item of items) {
        this.bindings.set(item.shortcut, item.bindings);
      }
    }
    disableShortcuts$.subscribe(x => (this.shortcutsDisabled = x));
    document.addEventListener('keydown', (e: KeyboardEvent) => {
      if (!isComboKey(e.key)) return;
      if (this.shouldSuppress(e)) return;
      this.comboKeyLastPressed = {key: e.key, timestampMs: Date.now()};
    });
  }

  public _testOnly_isEmpty() {
    return this.activeShortcuts.size === 0 && this.listeners.size === 0;
  }

  isInComboKeyMode() {
    return Object.values(ComboKey).some(key =>
      this.isInSpecificComboKeyMode(key)
    );
  }

  isInSpecificComboKeyMode(comboKey: ComboKey) {
    const {key, timestampMs} = this.comboKeyLastPressed;
    return (
      key === comboKey &&
      timestampMs &&
      Date.now() - timestampMs < COMBO_TIMEOUT_MS
    );
  }

  /**
   * TODO(brohlfs): Reconcile with the addShortcut() function in dom-util.
   * Most likely we will just keep this one here, but that is something for a
   * follow-up change.
   */
  addShortcut(
    element: HTMLElement,
    shortcut: Binding,
    listener: (e: KeyboardEvent) => void
  ) {
    const wrappedListener = (e: KeyboardEvent) => {
      if (e.repeat) return;
      if (!eventMatchesShortcut(e, shortcut)) return;
      if (shortcut.combo) {
        if (!this.isInSpecificComboKeyMode(shortcut.combo)) return;
      } else {
        if (this.isInComboKeyMode()) return;
      }
      if (this.shouldSuppress(e)) return;
      e.preventDefault();
      e.stopPropagation();
      listener(e);
    };
    element.addEventListener('keydown', wrappedListener);
    return () => element.removeEventListener('keydown', wrappedListener);
  }

  shouldSuppress(e: KeyboardEvent) {
    if (this.shortcutsDisabled) return true;
    if (shouldSuppress(e)) return true;

    // eg: {key: "k:keydown", ..., from: "gr-diff-view"}
    let key = `${e.key}:${e.type}`;
    if (this.isInSpecificComboKeyMode(ComboKey.G)) key = 'g+' + key;
    if (this.isInSpecificComboKeyMode(ComboKey.V)) key = 'v+' + key;
    if (e.shiftKey) key = 'shift+' + key;
    if (e.ctrlKey) key = 'ctrl+' + key;
    if (e.metaKey) key = 'meta+' + key;
    if (e.altKey) key = 'alt+' + key;
    let from = 'unknown';
    if (isElementTarget(e.currentTarget)) {
      from = e.currentTarget.tagName;
    }
    this.reporting?.reportInteraction('shortcut-triggered', {key, from});
    return false;
  }

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

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

  attachHost(host: HTMLElement, shortcuts: ShortcutListener[]) {
    this.activeShortcuts.set(
      host,
      shortcuts.map(s => s.shortcut)
    );
    const cleanups: (() => void)[] = [];
    for (const s of shortcuts) {
      const bindings = this.getBindingsForShortcut(s.shortcut);
      for (const binding of bindings ?? []) {
        if (binding.docOnly) continue;
        cleanups.push(this.addShortcut(document.body, binding, s.listener));
      }
    }
    this.cleanupsPerHost.set(host, cleanups);
    this.notifyViewListeners();
  }

  detachHost(host: HTMLElement) {
    this.activeShortcuts.delete(host);
    const cleanups = this.cleanupsPerHost.get(host);
    for (const cleanup of cleanups ?? []) cleanup();
    this.notifyViewListeners();
    return true;
  }

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

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

  getDescription(section: ShortcutSection, shortcutName: Shortcut) {
    const bindings = config.get(section);
    if (!bindings) return '';
    const binding = bindings.find(binding => binding.shortcut === shortcutName);
    return binding?.text ?? '';
  }

  getShortcut(shortcutName: Shortcut) {
    const bindings = this.bindings.get(shortcutName);
    if (!bindings) return '';
    return bindings
      .map(binding => describeBinding(binding).join('+'))
      .join(',');
  }

  activeShortcutsBySection() {
    const activeShortcuts = new Set<Shortcut>();
    for (const shortcuts of this.activeShortcuts.values()) {
      for (const shortcut of shortcuts) {
        activeShortcuts.add(shortcut);
      }
    }

    const activeShortcutsBySection = new Map<
      ShortcutSection,
      ShortcutHelpItem[]
    >();
    config.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<ShortcutSection, SectionView>();
    this.activeShortcutsBySection().forEach((shortcutHelps, section) => {
      const sectionView: 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: string[][]): string[][][] {
    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)));
      }
    }
    return [];
  }

  comboSetDisplayWidth(bindingDesc: string[][]) {
    const bindingSizer = (binding: string[]) =>
      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: Shortcut): string[][] | null {
    const bindings = this.bindings.get(shortcut);
    if (!bindings) return null;
    return bindings
      .filter(binding => !binding.docOnly)
      .map(binding => describeBinding(binding));
  }

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

function describeKey(key: string | Key) {
  switch (key) {
    case Key.UP:
      return '\u2191'; // ↑
    case Key.DOWN:
      return '\u2193'; // ↓
    case Key.LEFT:
      return '\u2190'; // ←
    case Key.RIGHT:
      return '\u2192'; // →
    default:
      return key;
  }
}

export function describeBinding(binding: Binding): string[] {
  const description: string[] = [];
  if (binding.combo === ComboKey.G) {
    description.push('g');
  }
  if (binding.combo === ComboKey.V) {
    description.push('v');
  }
  if (binding.modifiers?.includes(Modifier.SHIFT_KEY)) {
    description.push('Shift');
  }
  if (binding.modifiers?.includes(Modifier.ALT_KEY)) {
    description.push('Alt');
  }
  if (binding.modifiers?.includes(Modifier.CTRL_KEY)) {
    description.push('Ctrl');
  }
  if (binding.modifiers?.includes(Modifier.META_KEY)) {
    description.push('Meta/Cmd');
  }
  description.push(describeKey(binding.key));
  return description;
}
