import { ElementHandle } from 'puppeteer';
import { AsyncList, PageObjectElement, PageObjectElementList } from './page_object_element';

/**
 * A base class for writing page objects[1] that work both on in-browser and Puppeteer tests.
 *
 * A page object written as a subclass of PageObject will have two layers of wrapping:
 *
 *   1. The PageObject wraps a PageObjectElement.
 *   2. The PageObjectElement wraps either a DOM node (HTMLElement) or a Puppeteer handle
 *      (ElementHandle).
 *
 * The PageObjectElement wraps the root node of the component under test, and provides an
 * abstraction layer on top of the underlying DOM node or Puppeteer handle. A page object interacts
 * with the component under test exclusively via the PageObjectElement's API. This guarantees
 * compatibility with both in-browser and Puppeteer tests.
 *
 * PageObject and PageObjectElement are inspired by PageLoader[2], a Dart framework for creating
 * page objects compatible with both in-browser and WebDriver tests.
 *
 * For best practices, please see PageLoader Best Practices[3].
 *
 * [1] https://martinfowler.com/bliki/PageObject.html
 * [2] https://github.com/google/pageloader
 * [3] https://github.com/google/pageloader/blob/master/best_practices.md
 */
export abstract class PageObject {
  protected element: PageObjectElement;

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

  /** Returns true if the underlying PageObjectElement is empty. */
  async isEmpty(): Promise<boolean> {
    return await this.element.isEmpty();
  }

  /**
   * Returns the result of calling PageObjectElement#bySelector() on the underlying
   * PageObjectElement.
   */
  protected bySelector(selector: string): PageObjectElement {
    return this.element.bySelector(selector);
  }

  /**
   * Returns the result of calling PageObjectElement#bySelectorAll() on the underlying
   * PageObjectElement.
   */
  protected bySelectorAll(selector: string): PageObjectElementList  {
    return this.element.bySelectorAll(selector);
  }

  /** Instantiates a PageObject with the first element that matches the given selector. */
  protected poBySelector<T extends PageObject>(
      selector: string, ctor: { new(...args: any): T }): T {
    return new ctor(this.bySelector(selector));
  }

  /** Instantiates one PageObject for each element that match the given selector. */
  protected poBySelectorAll<T extends PageObject>(
      selector: string, ctor: { new(...args: any): T }): PageObjectList<T> {
    return new PageObjectList(this.bySelectorAll(selector)
        .map(async (poe: PageObjectElement) => new ctor(poe)));
  }
}

/** Convenience wrapper around a promise of a list of page objects. */
export class PageObjectList<T extends PageObject> extends AsyncList<T> {
  constructor(itemsPromise: Promise<T[]>) {
    super(itemsPromise);
  }
}
