// Copyright (C) 2019 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 m from 'mithril';
import {defer} from '../base/deferred';
import {Icon} from './icon';
import {scheduleFullRedraw} from './raf';

// This module deals with modal dialogs. Unlike most components, here we want to
// render the DOM elements outside of the corresponding vdom tree. For instance
// we might want to instantiate a modal dialog all the way down from a nested
// Mithril sub-component, but we want the result dom element to be nested under
// the root <body>.

// Usage:
// Full-screen modal use cases (the most common case)
// --------------------------------------------------
// - app.ts calls maybeRenderFullscreenModalDialog() when rendering the
//   top-level vdom, if a modal dialog is created via showModal()
// - The user (any TS code anywhere) calls showModal()
// - showModal() takes either:
//   - A static set of mithril vnodes (for cases when the contents of the modal
//     dialog is static and never changes)
//   - A function, invoked on each render pass, that returns mithril vnodes upon
//     each invocation.
//   - See examples in widgets_page.ts for both.
//
// Nested modal use-cases
// ----------------------
// A modal dialog can be created in a "positioned" layer (e.g., any div that has
// position:relative|absolute), so it's modal but only within the scope of that
// layer.
// In this case, just ust the Modal class as a standard mithril component.
// showModal()/closeModal() are irrelevant in this case.

export interface ModalAttrs {
  title: string;
  buttons?: ModalButton[];
  vAlign?: 'MIDDLE' /* default */ | 'TOP';

  // Used to disambiguate between different modal dialogs that might overlap
  // due to different client showing modal dialogs at the same time. This needs
  // to match the key passed to closeModal() (if non-undefined). If the key is
  // not provided, showModal will make up a random key in the showModal() call.
  key?: string;

  // A callback that is called when the dialog is closed, whether by pressing
  // any buttons or hitting ESC or clicking outside of the modal.
  onClose?: () => void;

  // The content/body of the modal dialog. This can be either:
  // 1. A static set of children, for simple dialogs which content never change.
  // 2. A factory method that returns a m() vnode for dyamic content.
  content?: m.Children | (() => m.Children);
}

export interface ModalButton {
  text: string;
  primary?: boolean;
  id?: string;
  action?: () => void;
}

// Usually users don't need to care about this class, as this is instantiated
// by showModal. The only case when users should depend on this is when they
// want to nest a modal dialog in a <div> they control (i.e. when the modal
// is scoped to a mithril component, not fullscreen).
export class Modal implements m.ClassComponent<ModalAttrs> {
  onbeforeremove(vnode: m.VnodeDOM<ModalAttrs>) {
    const removePromise = defer<void>();
    vnode.dom.addEventListener('animationend', () => {
      scheduleFullRedraw('force');
      removePromise.resolve();
    });
    vnode.dom.classList.add('modal-fadeout');

    // Retuning `removePromise` will cause Mithril to defer the actual component
    // removal until the fade-out animation is done. onremove() will be invoked
    // after this.
    return removePromise;
  }

  onremove(vnode: m.VnodeDOM<ModalAttrs>) {
    if (vnode.attrs.onClose !== undefined) {
      // The onClose here is the promise wrapper created by showModal(), which
      // in turn will: (1) call the user's original attrs.onClose; (2) resolve
      // the promise returned by showModal().
      vnode.attrs.onClose();
    }
  }

  oncreate(vnode: m.VnodeDOM<ModalAttrs>) {
    if (vnode.dom instanceof HTMLElement) {
      // Focus the newly created dialog, so that we react to Escape keydown
      // even if the user has not clicked yet on any element.
      // If there is a primary button, focus that, so Enter does the default
      // action. If not just focus the whole dialog.
      const primaryBtn = vnode.dom.querySelector('.modal-btn-primary');
      if (primaryBtn) {
        (primaryBtn as HTMLElement).focus();
      } else {
        vnode.dom.focus();
      }
      // If the modal dialog is instantiated in a tall scrollable container,
      // make sure to scroll it into the view.
      vnode.dom.scrollIntoView({block: 'center'});
    }
  }

  view(vnode: m.Vnode<ModalAttrs>) {
    const attrs = vnode.attrs;

    const buttons: m.Children = [];
    for (const button of attrs.buttons || []) {
      buttons.push(
        m(
          'button.modal-btn',
          {
            class: button.primary ? 'modal-btn-primary' : '',
            id: button.id,
            onclick: () => {
              closeModal(attrs.key);
              if (button.action !== undefined) button.action();
            },
          },
          button.text,
        ),
      );
    }

    const aria = '[aria-labelledby=mm-title][aria-model][role=dialog]';
    const align = attrs.vAlign === 'TOP' ? '.modal-dialog-valign-top' : '';
    return m(
      '.modal-backdrop',
      {
        onclick: this.onBackdropClick.bind(this, attrs),
        onkeyup: this.onBackdropKeyupdown.bind(this, attrs),
        onkeydown: this.onBackdropKeyupdown.bind(this, attrs),
        tabIndex: 0,
      },
      m(
        `.modal-dialog${align}${aria}`,
        m(
          'header',
          m('h2', {id: 'mm-title'}, attrs.title),
          m(
            'button[aria-label=Close Modal]',
            {onclick: () => closeModal(attrs.key)},
            m(Icon, {icon: 'close'}),
          ),
        ),
        m('main', vnode.children),
        buttons.length > 0 ? m('footer', buttons) : null,
      ),
    );
  }

  onBackdropClick(attrs: ModalAttrs, e: MouseEvent) {
    e.stopPropagation();
    // Only react when clicking on the backdrop. Don't close if the user clicks
    // on the dialog itself.
    const t = e.target;
    if (t instanceof Element && t.classList.contains('modal-backdrop')) {
      closeModal(attrs.key);
    }
  }

  onBackdropKeyupdown(attrs: ModalAttrs, e: KeyboardEvent) {
    e.stopPropagation();
    if (e.key === 'Escape' && e.type !== 'keyup') {
      closeModal(attrs.key);
    }
  }
}

// Set by showModal().
let currentModal: ModalAttrs | undefined = undefined;
let generationCounter = 0;

// This should be called only by app.ts and nothing else.
// This generates the modal dialog at the root of the DOM, so it can overlay
// on top of everything else.
export function maybeRenderFullscreenModalDialog() {
  // We use the generation counter as key to distinguish between: (1) two render
  // passes for the same dialog vs (2) rendering a new dialog that has been
  // created invoking showModal() while another modal dialog was already being
  // shown.
  if (currentModal === undefined) return [];
  let children: m.Children;
  if (currentModal.content === undefined) {
    children = null;
  } else if (typeof currentModal.content === 'function') {
    children = currentModal.content();
  } else {
    children = currentModal.content;
  }
  return [m(Modal, currentModal, children)];
}

// Shows a full-screen modal dialog.
export async function showModal(userAttrs: ModalAttrs): Promise<void> {
  const returnedClosePromise = defer<void>();
  const userOnClose = userAttrs.onClose ?? (() => {});

  // If the user doesn't specify a key (to match the closeModal), generate a
  // random key to distinguish two showModal({key:undefined}) calls.
  const key = userAttrs.key ?? `${++generationCounter}`;
  const attrs: ModalAttrs = {
    ...userAttrs,
    key,
    onClose: () => {
      userOnClose();
      returnedClosePromise.resolve();
    },
  };
  currentModal = attrs;
  redrawModal();
  return returnedClosePromise;
}

// Technically we don't need to redraw the whole app, but it's the more
// pragmatic option. This is exposed to keep the plugin code more clear, so it's
// evident why a redraw is requested.
export function redrawModal() {
  if (currentModal !== undefined) {
    scheduleFullRedraw('force');
  }
}

// Closes the full-screen modal dialog (if any).
// `key` is optional: if provided it will close the modal dialog only if the key
// matches. This is to avoid accidentally closing another dialog that popped
// in the meanwhile. If undefined, it closes whatever modal dialog is currently
// open (if any).
export function closeModal(key?: string) {
  if (
    currentModal === undefined ||
    (key !== undefined && currentModal.key !== key)
  ) {
    // Somebody else closed the modal dialog already, or opened a new one with
    // a different key.
    return;
  }
  currentModal = undefined;
  scheduleFullRedraw('force');
}

export function getCurrentModalKey(): string | undefined {
  return currentModal?.key;
}
