import { ElementHandle, Serializable } from 'puppeteer';
import {
  asyncFilter, asyncFind, asyncForEach, asyncMap,
} from '../async';

// Custom type guard to tell DOM elements and Puppeteer element handles apart.
function isPptrElement(
  element: HTMLElement | ElementHandle<HTMLElement>,
): element is ElementHandle<HTMLElement> {
  return (element as ElementHandle).asElement !== undefined;
}

/**
 * A helper class to write page objects[1] that work both on in-browser and Puppeteer tests.
 *
 * It's essentially a wrapper class that contains either a DOM node (HTMLElement) or a Puppeteer
 * handle (ElementHandle). Its API is analogous to that of HTMLElement, with the exception that
 * most functions return promises due to Puppeteer's asynchronous nature.
 *
 * A number of select* async methods are included to facilitate common tasks involving query
 * selectors and reduce the number of await statements in client code.
 *
 * To ensure compatibility with both in-browser and Puppeteer tests, page objects must be built
 * exclusively using PageObjectElement without ever referencing DOM nodes or Puppeteer element
 * handles directly.
 *
 * PageObjectElement is inspired by PageLoader[2], a Dart framework for creating page objects
 * compatible with both in-browser and WebDriver tests.
 *
 * [1] https://martinfowler.com/bliki/PageObject.html
 * [2] https://github.com/google/pageloader
 */
export class PageObjectElement {
  private readonly elementPromise: Promise<HTMLElement | ElementHandle<HTMLElement> | null>;

  constructor(
    element:
          HTMLElement |
          ElementHandle<HTMLElement> |
          Promise<HTMLElement | ElementHandle<HTMLElement> | null>,
  ) {
    if (element instanceof Promise) {
      this.elementPromise = element;
    } else {
      this.elementPromise = new Promise((resolve) => resolve(element));
    }
  }

  /** Returns true if the underlying DOM node or Puppeteer handle is empty. */
  async isEmpty(): Promise<boolean> {
    return !(await this.elementPromise);
  }

  /// //////////////////////////////////////////////////////////////
  // Wrappers around various HTMLElement methods and properties. //
  /// //////////////////////////////////////////////////////////////

  // Please add any missing wrappers as needed.

  /** Analogous to HTMLElement#innerText. */
  get innerText(): Promise<string> {
    return this.applyFnToDOMNode((el) => el.innerText);
  }

  /** Returns true if the element's inner text equals the given string. */
  async isInnerTextEqualTo(text: string): Promise<boolean> {
    return (await this.innerText) === text;
  }

  /** Analogous to HTMLElement#className. */
  get className(): Promise<string> {
    return this.applyFnToDOMNode((el) => el.className);
  }

  /** Returns true if the element has the given CSS class. */
  async hasClassName(className: string) {
    return this.applyFnToDOMNode(
      (el, className) => el.classList.contains(className as string),
      className,
    );
  }

  /** Analogous to HTMLElement#focus(). */
  async focus() {
    const element = await this.elementPromise;
    await element!.focus();
  }

  /** Analogous to HTMLElement#click(). */
  async click() {
    const element = await this.elementPromise;
    await element!.click();
  }

  /** Analogous to HTMLElement#hasAttribute(). */
  async hasAttribute(attribute: string): Promise<boolean> {
    return this.applyFnToDOMNode(
      (el, attribute) => el.hasAttribute(attribute as string), attribute,
    );
  }

  /** Analogous to HTMLElement#getAttribute(). */
  async getAttribute(attribute: string): Promise<string | null> {
    return this.applyFnToDOMNode(
      (el, attribute) => el.getAttribute(attribute as string), attribute,
    );
  }

  /** Analogous to the HTMLElement#value property getter (e.g. for text inputs, selects, etc.). */
  get value(): Promise<string> {
    return this.applyFnToDOMNode((el) => (el as HTMLInputElement).value);
  }

  /**
   * Sends a single key press.
   *
   * Sends actual key presses on Puppeteer. Simulates events "keydown", "keypress" and "keyup" on
   * the browser.
   *
   * @param key The "key" attribute of the KeyboardEvent to be dispatched.
   */
  async typeKey(key: string) {
    const element = await this.elementPromise;
    if (isPptrElement(element!)) {
      return element.type(key);
    }
    element!.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, key: key }));
    element!.dispatchEvent(new KeyboardEvent('keypress', { bubbles: true, key: key }));
    element!.dispatchEvent(new KeyboardEvent('keyup', { bubbles: true, key: key }));
  }

  /**
   * Analogous to the HTMLElement#value property setter (e.g. for text inputs, selects, etc.).
   *
   * Simulates events "input" and "change".
   *
   * Note: Only one "input" event is dispatched. The browser normally dispatches one "input" event
   * per keystroke.
   */
  async enterValue(value: string) {
    // A future version of this method might take advantage of Puppeteer's ElementHandle.type()
    // method and/or simulate DOM events in a more realistic way as done in the PageLoader library:
    // https://github.com/google/pageloader/blob/80766100da9fe05d99eb92edd69b7ddfa82cc10e/lib/src/html/html_page_loader_element.dart#L393.
    await this.applyFnToDOMNode((el, value) => {
      // The below type union is non-exhaustive and for illustration purposes only.
      (el as HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement).value = value as string;

      // Simulate a subset of the input events (just one). This should be enough for most tests.
      el.dispatchEvent(new Event('input', { bubbles: true }));
      el.dispatchEvent(new Event('change', { bubbles: true }));
    }, value);
  }

  /**
   * Returns the result of evaluating the given function, passing the wrapped HTMLElement (i.e.
   * the DOM node) as the first argument, followed by any number of Serializable parameters.
   *
   * The function will be evaluated natively or via Puppeteer according to the type of the wrapped
   * element.
   */
  async applyFnToDOMNode<T extends Serializable | void>(
    fn: (element: HTMLElement, ...args: Serializable[])=> T,
    ...args: Serializable[]
  ): Promise<T> {
    const element = await this.elementPromise;
    if (isPptrElement(element!)) {
      return await element.evaluate(fn, ...args) as T;
    }
    return fn(element!, ...args);
  }

  /// /////////////////////////////////////////////////////////////////
  // Query selectors and convenience methods using query selectors. //
  /// /////////////////////////////////////////////////////////////////

  /** Analogous to HTMLElement#querySelector(). */
  bySelector(selector: string): PageObjectElement {
    return new PageObjectElement(this.elementPromise.then((element) => {
      if (!element) {
        return new Promise((resolve) => resolve(null));
      }
      if (isPptrElement(element)) {
        // Note that common-sk functions $ and $$ are aliases for HTMLElement#querySelectorAll() and
        // HTMLElement#querySelector(), respectively, whereas Puppeteer's ElementHandle#$() and
        // ElementHandle#$$() methods are the other way around.
        return element.$(selector);
      }
      return new Promise((resolve) => resolve(element.querySelector<HTMLElement>(selector)));
    }));
  }

  /** Analogous to HTMLElement#querySelectorAll(). */
  bySelectorAll(selector: string): PageObjectElementList {
    return new PageObjectElementList(this.elementPromise.then((element) => {
      if (!element) {
        return [];
      }
      if (isPptrElement(element)) {
        // Note that common-sk functions $ and $$ are aliases for HTMLElement#querySelectorAll() and
        // HTMLElement#querySelector(), respectively, whereas Puppeteer's ElementHandle#$() and
        // ElementHandle#$$() methods are the other way around.
        return element.$$(selector);
      }
      return new Promise((resolve) => resolve(Array.from(element.querySelectorAll<HTMLElement>(selector))));
    }));
  }
}

/** Convenience wrapper around a promise that returns a list. */
export abstract class AsyncList<T> {
  private readonly itemsPromise: Promise<T[]>;

  protected constructor(items?: Promise<T[]>) {
    if (!items) {
      items = new Promise<T[]>((resolve) => resolve([]));
    }
    this.itemsPromise = items;
  }

  /** Returns the item with the given index from the list. */
  async item(index: number): Promise<T> {
    return (await this.itemsPromise)[index];
  }

  /** Analogous to Array.prototype.length. */
  get length(): Promise<number> {
    return this.itemsPromise.then((items) => items.length);
  }

  /** Analogous to Array.prototype.filter, where the callback function returns a promise. */
  filter(fn: (item: T, index: number)=> Promise<boolean>): Promise<T[]> {
    return asyncFilter(this.itemsPromise, fn);
  }

  /** Analogous to Array.prototype.find, where the callback function returns a promise. */
  find(fn: (item: T, index: number)=> Promise<boolean>): Promise<T | null> {
    return asyncFind(this.itemsPromise, fn);
  }

  /** Analogous to Array.prototype.forEach, where the callback function returns a promise. */
  forEach(fn: (item: T, index: number)=> Promise<void>): Promise<void> {
    return asyncForEach(this.itemsPromise, fn);
  }

  /** Analogous to Array.prototype.map, where the callback function returns a promise. */
  map<U>(fn: (item: T, index: number)=> Promise<U>): Promise<U[]> {
    return asyncMap(this.itemsPromise, fn);
  }
}

/** Convenience wrapper around a Promise<PageObjectElement[]>. */
export class PageObjectElementList extends AsyncList<PageObjectElement> {
  constructor(itemsPromise?: Promise<HTMLElement[] | ElementHandle<HTMLElement>[]>) {
    super(itemsPromise?.then((items) => items.map((item: HTMLElement | ElementHandle<HTMLElement>) => new PageObjectElement(item))));
  }
}
