import express from 'express';
import * as fs from 'fs';
import * as path from 'path';
import * as http from 'http';
import * as net from 'net';
import puppeteer from 'puppeteer';
import webpack from 'webpack';
import webpackDevMiddleware from 'webpack-dev-middleware';

// File inside $ENV_DIR containing the demo page server's TCP port. Only applies to Bazel tests
// using the test_on_env rule.
const ENV_PORT_FILE_BASE_NAME = 'port';

/** A DOM event name. */
export type EventName = string;

/**
 * Type of the function returned by addEventListenersToPuppeteerPage.
 *
 * It returns a promise that resolves when an event e of the given name is
 * caught, and returns e.detail (assumed to be of type T).
 *
 * The generic type variable T is analogous to T in e.g. CustomEvent<T>.
 *
 * Note: this works for standard DOM events as well, not just custom events.
 */
export type EventPromiseFactory = <T>(eventName: EventName) => Promise<T>;

/**
 * This function allows tests to catch document-level events in a Puppeteer
 * page.
 *
 * It takes a Puppeteer page and a list of event names, and adds event listeners
 * to the page's document for the given events. It must be called before the
 * page is loaded with e.g. page.goto() for it to work.
 *
 * The returned function takes an event name in eventNames and returns a promise
 * that will resolve to the corresponding Event object's "detail" field when the
 * event is caught. Multiple promises for the same event will be resolved in the
 * order that they were created, i.e. one caught event resolves the oldest
 * pending promise.
 */
export const addEventListenersToPuppeteerPage = async (page: puppeteer.Page, eventNames: EventName[]) => {
  // Maps event names to FIFO queues of promise resolver functions.
  const resolverFnQueues = new Map<EventName, Function[]>();
  eventNames.forEach((eventName) => resolverFnQueues.set(eventName, []));

  // Use an unlikely prefix to reduce chances of name collision.
  await page.exposeFunction('__pptr_onEvent', (eventName: EventName, eventDetail: any) => {
    const resolverFn = resolverFnQueues.get(eventName)!.shift(); // Dequeue.
    if (resolverFn) { // Undefined if queue length was 0.
      resolverFn(eventDetail);
    }
  });

  // This function will be executed inside the Puppeteer page for each of the
  // events we want to listen for. It adds an event listener that will call the
  // function we've exposed in the previous step.
  const addEventListener = (name: EventName) => {
    document.addEventListener(name, (event: Event) => {
      (window as any).__pptr_onEvent(name, (event as any).detail);
    });
  };

  // Add an event listener for each one of the given events.
  const promises = eventNames.map((name) => page.evaluateOnNewDocument(addEventListener, name));
  await Promise.all(promises);

  // The returned function takes an event name and returns a promise that will
  // resolve to the event details when the event is caught.
  const eventPromiseFactory: EventPromiseFactory = (eventName: EventName) => {
    if (!resolverFnQueues.has(eventName)) {
      // Fail if the event wasn't included in eventNames.
      throw new Error(`no event listener for "${eventName}"`);
    }
    return new Promise(
      // Enqueue resolver function at the end of the queue.
      (resolve) => resolverFnQueues.get(eventName)!.push(resolve),
    );
  };

  return eventPromiseFactory;
};

/**
 * Returns true if running from within a Docker container, or false otherwise.
 */
export const inDocker = () => fs.existsSync('/.dockerenv');

/**
 * Returns true if running from Bazel (e.g. with "bazel test"), or false otherwise.
 */
export const inBazel = () => !!process.env.BAZEL_WORKSPACE;

/**
 * Launches a Puppeteer browser.
 */
export const launchBrowser = () => puppeteer.launch(
  // These options are required to run Puppeteer from within a Docker container, as is the case
  // under Bazel and RBE. See
  // https://github.com/puppeteer/puppeteer/blob/master/docs/troubleshooting.md#running-puppeteer-in-docker.
  //
  // Flag --no-sandbox is necessary to run Puppeteer tests under Bazel locally (i.e. not on RBE) on
  // a Swarming bot. If we do not provide said flag, we get the following error:
  //
  //     No usable sandbox! Update your kernel or see
  //     https://chromium.googlesource.com/chromium/src/+/master/docs/linux/suid_sandbox_development.md
  //     for more information on developing with the SUID sandbox. If you want to live dangerously
  //     and need an immediate workaround, you can try using --no-sandbox.
  { args: ['--disable-dev-shm-usage', '--no-sandbox'] },
);

/**
 * Type of the object returned by setUpPuppeteerAndDemoPageServer.
 *
 * A test suite should reuse this object in all its test cases. This object's
 * fields will be automatically updated with a fresh page and base URL before
 * each test case is executed.
 */
export interface TestBed {
  page: puppeteer.Page;
  baseUrl: string;
};

/**
 * Starts a web server that serves custom element demo pages. Equivalent to
 * running "npx webpack-dev-server" on the terminal.
 *
 * Demo pages can be accessed at the returned baseUrl. For example, page
 * my-component-sk-demo.html is found at `${baseUrl}/dist/my-component-sk.html`.
 *
 * This function should be called once at the beginning of any test suite that
 * requires custom element demo pages. The returned function stopDemoPageServer
 * should be called at the end of the test suite.
 */
export const startWebpackDemoPageServer = async (pathToWebpackConfigTs: string) => {
  // Load Webpack configuration.
  const webpackConfigFactory = require(pathToWebpackConfigTs) as webpack.ConfigurationFactory;
  const configuration = webpackConfigFactory('', { mode: 'development' }) as webpack.Configuration;

  // Prevent the creation of source maps, which can consume lots of memory.
  // https://github.com/webpack/webpack-sources/issues/66#issuecomment-537526984
  delete configuration.devtool;

  // This is equivalent to running "npx webpack-dev-server" on the terminal.
  const middleware = webpackDevMiddleware(webpack(configuration), {
    logLevel: 'warn', // Do not print summary on startup.
  } as any);
  await new Promise((resolve) => middleware.waitUntilValid(resolve));

  // Start an HTTP server on a random, unused port. Serve the above middleware.
  const app = express();
  app.use(configuration.output!.publicPath! || '', middleware); // Serve on e.g. /dist.
  let server: http.Server;
  await new Promise((resolve) => { server = app.listen(0, () => resolve(undefined)); });

  return {
    // Base URL for the demo page server.
    baseUrl: `http://localhost:${(server!.address() as net.AddressInfo).port}`,

    // Call this function to shut down the HTTP server after tests are finished.
    stopDemoPageServer: async () => {
      await Promise.all([
        new Promise((resolve) => middleware.close(() => resolve(undefined))),
        new Promise((resolve) => server.close(resolve)),
      ]);
    },
  };
};

/**
 * Returns the output directory where tests should e.g. save screenshots.
 * Screenshots saved in this directory will be uploaded to Gold.
 */
export const outputDir = () => {
  // When running via "bazel test", screenshots for e.g. //path/to/my:puppeteer_test will be found
  // at //bazel-testlogs/path/to/my/puppeteer_test/test.outputs/outputs.zip. This is true when
  // running on RBE as well (e.g. "bazel test --config=remote").
  //
  // See the following link for more:
  // https://docs.bazel.build/versions/master/test-encyclopedia.html#test-interaction-with-the-filesystem.
  if (exports.inBazel()) {
    const undeclaredOutputsDir = process.env.TEST_UNDECLARED_OUTPUTS_DIR;
    if (!undeclaredOutputsDir) {
      throw new Error('required environment variable TEST_UNDECLARED_OUTPUTS_DIR is unset');
    }
    const outputDir = path.join(undeclaredOutputsDir, 'puppeteer-test-screenshots');
    if (!fs.existsSync(outputDir)) {
      fs.mkdirSync(outputDir);
    }
    return outputDir;
  }

  // In the pre-Bazel world, Puppeteer tests either run inside the puppeteer-tests Docker container
  // (e.g. Infra-PerCommit-Puppeteer), or locally during development.
  if (exports.inDocker()) {
    return '/out';
  }

  // Resolves to //puppeteer-tests/output when running locally.
  return path.join(__dirname, 'output');
};

/**
 * Takes a screenshot and saves it to the tests output directory to be uploaded
 * to Gold.
 *
 * The screenshot will be saved as <appName>_<testName>.png. Using the
 * application name as a prefix prevents name collisions between different apps
 * and increases consistency among test names.
 */
export const takeScreenshot =
    (handle: puppeteer.Page | puppeteer.ElementHandle, appName: string, testName: string) =>
  handle.screenshot({path: path.join(exports.outputDir(), `${appName}_${testName}.png`)});


let browser: puppeteer.Browser;
let testBed: Partial<TestBed>;

/**
 * Once per Mocha invocation, loadCachedTestBed will compile all the demo pages and launch a
 * Puppeteer browser window to run the tests. On all subsequent calls, it will return essentially
 * a cached handle to that invocation.
 *
 * Test cases can access the demo page server's base URL and a Puppeteer page ready to be used via
 * the return value's baseUrl and page objects, respectively.
 *
 * This function assumes that each test case uses exactly one Puppeteer page (that's why it doesn't
 * expose the Browser instance to tests). The page is set up with a cookie (name: "puppeteer",
 * value: "true") to give demo pages a means to detect whether they are running within Puppeteer or
 * not.
 */
export async function loadCachedTestBed(pathToWebpackConfigTs: string) {
  if (testBed) {
    return testBed as TestBed;
  }
  const newTestBed: Partial<TestBed> = {};

  if (inBazel()) {
    // Read the demo page server's TCP port.
    const envDir = process.env.ENV_DIR;
    if (!envDir) throw new Error('required environment variable ENV_DIR is unset');
    const port = parseInt(fs.readFileSync(path.join(envDir, ENV_PORT_FILE_BASE_NAME), 'utf8'));
    newTestBed.baseUrl = `http://localhost:${port}`
  } else {
    // Not in Bazel - Start the Webpack-based demo page server.
    let baseUrl;
    ({ baseUrl } = await startWebpackDemoPageServer(pathToWebpackConfigTs));
    newTestBed.baseUrl = baseUrl; // Make baseUrl available to tests.
  }

  browser = await launchBrowser();
  testBed = newTestBed;
  setBeforeAfterHooks();
  return testBed as TestBed;
}

// This sets up some handy helpers to load a new page and shut it down w/o having to expose
// the puppeteer.Browser object to the callers.
function setBeforeAfterHooks() {
  beforeEach(async () => {
    testBed.page = await browser.newPage(); // Make page available to tests.

    // Tell demo pages this is a Puppeteer test. Demo pages should not fake RPC
    // latency, render animations or exhibit any other non-deterministic
    // behavior that could result in differences in the screenshots uploaded to
    // Gold.
    await testBed.page.setCookie({
      url: testBed.baseUrl,
      name: 'puppeteer',
      value: 'true'
    });
  });

  afterEach(async () => {
    await testBed.page!.close();
  });

  // When running under Bazel, we need to explicitly shut down Puppeteer, otherwise tests will run
  // forever, eventually timing out and failing.
  if (inBazel()) {
    after(async () => {
      await browser.close();
    });
  }
}