// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import {assert} from 'chrome://resources/js/assert_ts.js';
import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js';

import {NamedDestinationMessageData, Rect, SaveRequestType} from './constants.js';
import {PdfPluginElement} from './internal_plugin.js';
import {PinchPhase, Viewport} from './viewport.js';

export interface MessageData {
  type: string;
  messageId?: string;
}

export interface SaveAttachmentMessageData {
  type: string;
  dataToSave: ArrayBuffer;
  messageId: string;
}

interface SaveDataMessageData {
  dataToSave: ArrayBuffer;
  token: string;
  fileName: string;
}

export interface PrintPreviewParams {
  type: string;
  url: string;
  grayscale: boolean;
  modifiable: boolean;
  pageNumbers: number[];
}

interface ThumbnailMessageData {
  imageData: ArrayBuffer;
  width: number;
  height: number;
}

/**
 * Creates a cryptographically secure pseudorandom 128-bit token.
 * @return The generated token as a hex string.
 */
function createToken(): string {
  const randomBytes = new Uint8Array(16);
  window.crypto.getRandomValues(randomBytes);
  return Array.from(randomBytes, b => b.toString(16).padStart(2, '0')).join('');
}

export interface ContentController {
  isActive: boolean;

  getEventTarget(): EventTarget;
  beforeZoom(): void;
  afterZoom(): void;
  viewportChanged(): void;
  rotateClockwise(): void;
  rotateCounterclockwise(): void;
  setDisplayAnnotations(displayAnnotations: boolean): void;
  setTwoUpView(enableTwoUpView: boolean): void;

  /** Triggers printing of the current document. */
  print(): void;

  /** Undo an edit action. */
  undo(): void;

  /** Redo an edit action. */
  redo(): void;

  /**
   * Requests that the current document be saved.
   * @param requestType The type of save request. If ANNOTATION, a response is
   *     required, otherwise the controller may save the document to disk
   *     internally.
   */
  save(requestType: SaveRequestType): Promise<{
    fileName: string,
    dataToSave: ArrayBuffer,
    editModeForTesting?: boolean,
  }|null>;

  /**
   * Requests that the attachment at a certain index be saved.
   * @param index The index of the attachment to be saved.
   */
  saveAttachment(index: number): Promise<SaveAttachmentMessageData>;

  /** Loads PDF document from `data` activates UI. */
  load(fileName: string, data: ArrayBuffer): Promise<void>;

  /** Unloads the current document and removes the UI. */
  unload(): void;
}

/** Event types dispatched by the plugin controller. */
export enum PluginControllerEventType {
  IS_ACTIVE_CHANGED = 'PluginControllerEventType.IS_ACTIVE_CHANGED',
  PLUGIN_MESSAGE = 'PluginControllerEventType.PLUGIN_MESSAGE',
}

/**
 * PDF plugin controller singleton, responsible for communicating with the
 * embedded plugin element. Dispatches a
 * `PluginControllerEventType.PLUGIN_MESSAGE` event containing the message from
 * the plugin, if a message type not handled by this controller is received.
 */
export class PluginController implements ContentController {
  private eventTarget_: EventTarget = new EventTarget();
  private isActive_: boolean = false;
  private plugin_: PdfPluginElement;
  private delayedMessages_: Array<{message: any, transfer?: Transferable[]}>|
      null = [];
  private viewport_: Viewport;
  private getIsUserInitiatedCallback_: () => boolean;
  private getLoadedCallback_: () => Promise<void>| null;
  private pendingTokens_:
      Map<string,
          PromiseResolver<{fileName: string, dataToSave: ArrayBuffer}|null>>;
  private requestResolverMap_: Map<string, PromiseResolver<any>>;
  private uidCounter_: number = 1;

  init(
      plugin: HTMLEmbedElement, viewport: Viewport,
      getIsUserInitiatedCallback: () => boolean,
      getLoadedCallback: () => Promise<void>| null) {
    this.plugin_ = plugin as PdfPluginElement;
    this.plugin_.addEventListener(
        'message', e => this.handlePluginMessage_(e as MessageEvent), false);
    this.plugin_.postMessage = (message, transfer) => {
      this.delayedMessages_!.push({message, transfer});
    };

    this.viewport_ = viewport;
    this.getIsUserInitiatedCallback_ = getIsUserInitiatedCallback;
    this.getLoadedCallback_ = getLoadedCallback;
    this.pendingTokens_ = new Map();
    this.requestResolverMap_ = new Map();

    this.viewport_.setContent(this.plugin_);
    this.viewport_.setRemoteContent(this.plugin_);
  }

  get isActive(): boolean {
    // Check whether `plugin_` is defined as a signal that `init()` was called.
    return !!this.plugin_ && this.isActive_;
  }

  set isActive(isActive: boolean) {
    const wasActive = this.isActive;
    this.isActive_ = isActive;
    if (this.isActive === wasActive) {
      return;
    }

    this.eventTarget_.dispatchEvent(new CustomEvent(
        PluginControllerEventType.IS_ACTIVE_CHANGED, {detail: this.isActive}));
  }

  private createUid_(): number {
    return this.uidCounter_++;
  }

  getEventTarget() {
    return this.eventTarget_;
  }

  viewportChanged() {}

  redo() {}

  undo() {}

  /**
   * Notify the plugin to stop reacting to scroll events while zoom is taking
   * place to avoid flickering.
   */
  beforeZoom() {
    this.postMessage_({type: 'stopScrolling'});

    if (this.viewport_.pinchPhase === PinchPhase.START) {
      const position = this.viewport_.position;
      const zoom = this.viewport_.getZoom();
      const pinchPhase = this.viewport_.pinchPhase;
      const layoutOptions = this.viewport_.getLayoutOptions();
      this.postMessage_({
        type: 'viewport',
        userInitiated: true,
        zoom: zoom,
        layoutOptions: layoutOptions,
        xOffset: position.x,
        yOffset: position.y,
        pinchPhase: pinchPhase,
      });
    }
  }

  /**
   * Notify the plugin of the zoom change and to continue reacting to scroll
   * events.
   */
  afterZoom() {
    const position = this.viewport_.position;
    const zoom = this.viewport_.getZoom();
    const layoutOptions = this.viewport_.getLayoutOptions();
    const pinchVector = this.viewport_.pinchPanVector || {x: 0, y: 0};
    const pinchCenter = this.viewport_.pinchCenter || {x: 0, y: 0};
    const pinchPhase = this.viewport_.pinchPhase;

    this.postMessage_({
      type: 'viewport',
      userInitiated: this.getIsUserInitiatedCallback_(),
      zoom: zoom,
      layoutOptions: layoutOptions,
      xOffset: position.x,
      yOffset: position.y,
      pinchPhase: pinchPhase,
      pinchX: pinchCenter.x,
      pinchY: pinchCenter.y,
      pinchVectorX: pinchVector.x,
      pinchVectorY: pinchVector.y,
    });
  }

  /**
   * Post a message to the plugin. Some messages will cause an async reply to be
   * received through handlePluginMessage_().
   */
  private postMessage_<M extends MessageData>(message: M) {
    this.plugin_.postMessage(message);
  }

  /**
   * Post a message to the plugin, for cases where direct response is expected
   * from the plugin.
   * @return A promise holding the response from the plugin.
   */
  private postMessageWithReply_<T, M extends MessageData>(message: M):
      Promise<T> {
    const promiseResolver = new PromiseResolver<T>();
    message.messageId = `${message.type}_${this.createUid_()}`;
    this.requestResolverMap_.set(message.messageId, promiseResolver);
    this.postMessage_(message);
    return promiseResolver.promise;
  }

  rotateClockwise() {
    this.postMessage_({type: 'rotateClockwise'});
  }

  rotateCounterclockwise() {
    this.postMessage_({type: 'rotateCounterclockwise'});
  }

  setDisplayAnnotations(displayAnnotations: boolean) {
    this.postMessage_({
      type: 'displayAnnotations',
      display: displayAnnotations,
    });
  }

  setTwoUpView(enableTwoUpView: boolean) {
    this.postMessage_({
      type: 'setTwoUpView',
      enableTwoUpView: enableTwoUpView,
    });
  }

  print() {
    this.postMessage_({type: 'print'});
  }

  selectAll() {
    this.postMessage_({type: 'selectAll'});
  }

  getSelectedText(): Promise<{selectedText: string}> {
    return this.postMessageWithReply_({type: 'getSelectedText'});
  }

  /**
   * Post a thumbnail request message to the plugin.
   * @return A promise holding the thumbnail response from the plugin.
   */
  requestThumbnail(page: number): Promise<ThumbnailMessageData> {
    return this.postMessageWithReply_({
      type: 'getThumbnail',
      // The plugin references pages using zero-based indices.
      page: page - 1,
    });
  }

  resetPrintPreviewMode(printPreviewParams: PrintPreviewParams) {
    this.postMessage_({
      type: 'resetPrintPreviewMode',
      url: printPreviewParams.url,
      grayscale: printPreviewParams.grayscale,
      // If the PDF isn't modifiable we send 0 as the page count so that no
      // blank placeholder pages get appended to the PDF.
      pageCount:
          (printPreviewParams.modifiable ?
               printPreviewParams.pageNumbers.length :
               0),
    });
  }

  /**
   * @param color New color, as a 32-bit integer, of the PDF plugin
   *     background.
   */
  setBackgroundColor(color: number) {
    this.postMessage_({
      type: 'setBackgroundColor',
      color: color,
    });
  }

  loadPreviewPage(url: string, index: number) {
    this.postMessage_({type: 'loadPreviewPage', url: url, index: index});
  }

  getPageBoundingBox(page: number): Promise<Rect> {
    return this.postMessageWithReply_({
      type: 'getPageBoundingBox',
      page,
    });
  }

  getPasswordComplete(password: string) {
    this.postMessage_({type: 'getPasswordComplete', password: password});
  }

  /**
   * @return A promise holding the named destination information from the
   *     plugin.
   */
  getNamedDestination(destination: string):
      Promise<NamedDestinationMessageData> {
    return this.postMessageWithReply_({
      type: 'getNamedDestination',
      namedDestination: destination,
    });
  }

  setPresentationMode(enablePresentationMode: boolean) {
    this.postMessage_({
      type: 'setPresentationMode',
      enablePresentationMode,
    });
  }

  save(requestType: SaveRequestType) {
    const resolver =
        new PromiseResolver<{fileName: string, dataToSave: ArrayBuffer}|null>();
    const newToken = createToken();
    this.pendingTokens_.set(newToken, resolver);
    this.postMessage_({
      type: 'save',
      token: newToken,
      saveRequestType: requestType,
    });
    return resolver.promise;
  }

  saveAttachment(index: number): Promise<SaveAttachmentMessageData> {
    return this.postMessageWithReply_({
      type: 'saveAttachment',
      attachmentIndex: index,
    });
  }

  async load(_fileName: string, data: ArrayBuffer) {
    // Load `data` into the PDF plugin. The plugin transfers the data to be
    // loaded within the inner frame.
    this.viewport_.setRemoteContent(this.plugin_);
    this.plugin_.postMessage({type: 'loadArray', dataToLoad: data}, [data]);

    this.plugin_.style.display = 'block';
    await this.getLoadedCallback_();
    this.isActive = true;
  }

  unload() {
    this.plugin_.style.display = 'none';
    this.isActive = false;
  }

  /**
   * Binds an event handler for messages received from the plugin.
   *
   * TODO(crbug.com/1228987): Remove this method when a permanent postMessage()
   * bridge is implemented for the viewer.
   */
  bindMessageHandler(port: MessagePort) {
    assert(this.delayedMessages_ !== null);
    assert(this.plugin_);
    const delayedMessages = this.delayedMessages_;
    this.delayedMessages_ = null;

    this.plugin_.postMessage = port.postMessage.bind(port);
    port.onmessage = e => this.handlePluginMessage_(e);

    for (const {message, transfer} of delayedMessages) {
      this.plugin_.postMessage(message, transfer);
    }
  }

  /**
   * An event handler for handling message events received from the plugin.
   */
  private handlePluginMessage_(messageEvent: MessageEvent) {
    const messageData = messageEvent.data;

    // Handle case where this Plugin->Page message is a direct response
    // to a previous Page->Plugin message
    if (messageData.messageId !== undefined) {
      const resolver =
          this.requestResolverMap_.get(messageData.messageId) || null;
      assert(resolver !== null);
      this.requestResolverMap_.delete(messageData.messageId);
      resolver.resolve(messageData);
      return;
    }

    switch (messageData.type) {
      case 'gesture':
        this.viewport_.dispatchGesture(messageData.gesture);
        break;
      case 'swipe':
        this.viewport_.dispatchSwipe(messageData.direction);
        break;
      case 'goToPage':
        this.viewport_.goToPage(messageData.page);
        break;
      case 'setScrollPosition':
        this.viewport_.scrollTo(messageData);
        break;
      case 'scrollBy':
        this.viewport_.scrollBy(messageData);
        break;
      case 'syncScrollFromRemote':
        this.viewport_.syncScrollFromRemote(messageData);
        break;
      case 'ackScrollToRemote':
        this.viewport_.ackScrollToRemote(messageData);
        break;
      case 'saveData':
        this.saveData_(messageData);
        break;
      case 'consumeSaveToken':
        const resolver = this.pendingTokens_.get(messageData.token);
        assert(resolver);
        assert(this.pendingTokens_.delete(messageData.token));
        resolver.resolve(null);
        break;
      default:
        this.eventTarget_.dispatchEvent(new CustomEvent(
            PluginControllerEventType.PLUGIN_MESSAGE, {detail: messageData}));
    }
  }

  /** Handles the pdf file buffer received from the plugin. */
  private saveData_(messageData: SaveDataMessageData) {
    // Verify a token that was created by this instance is included to avoid
    // being spammed.
    const resolver = this.pendingTokens_.get(messageData.token);
    assert(resolver);
    assert(this.pendingTokens_.delete(messageData.token));

    if (!messageData.dataToSave) {
      resolver.reject();
      return;
    }

    // Verify the file size and the first bytes to make sure it's a PDF. Cap at
    // 100 MB. This cap should be kept in sync with and is also enforced in
    // pdf/out_of_process_instance.cc.
    const MIN_FILE_SIZE = '%PDF1.0'.length;
    const MAX_FILE_SIZE = 100 * 1000 * 1000;

    const buffer = messageData.dataToSave;
    const bufView = new Uint8Array(buffer);
    assert(
        bufView.length <= MAX_FILE_SIZE,
        `File too large to be saved: ${bufView.length} bytes.`);
    assert(bufView.length >= MIN_FILE_SIZE);
    assert(
        String.fromCharCode(bufView[0], bufView[1], bufView[2], bufView[3]) ===
        '%PDF');

    resolver.resolve(messageData);
  }

  static getInstance(): PluginController {
    return instance || (instance = new PluginController());
  }
}

let instance: PluginController|null = null;
