const puppeteer = require('puppeteer');
const genericPool = require('generic-pool');

class Browser {
  constructor(page) {
    this.page = page;
    // this.page.on('error', console.error.bind(console));
    // this.page.on('pageerror', console.error.bind(console));
    // this.page.on('console', console.log.bind(console));
  }
  setContent(htmlContent) {
    return this.page.evaluate((html) => {
      document.documentElement.innerHTML = html;
    }, htmlContent);
  }
  goto(url) {
    return this.page.goto(url, {
      timeout: 60 * 1000, // 1 minute is a long time, but heh.
    });
  }
  waitForNavigation(...args) {
    return this.page.waitForNavigation(...args);
  }
  evaluate(...args) {
    return this.page.evaluate(...args);
  }
  close() {
    return this.page.close();
  }
}

const launchBrowser = () => puppeteer.launch({
  headless: process.env.HEADLESS === 'true',
  devtools: process.env.DEV_TOOLS === 'true',
  ignoreHTTPSErrors: true,
});

const instantiatePool = async ({ min, max }) => {
  const browser = await launchBrowser();

  const factory = {
    async create() {
      // @todo if create throws, scraperjs will call create again
      // the caller does not seem to check errors proeprly
      // hopefully we can catch the errors here, and launch a new browser.
      const page = await browser.newPage();

      // this currently causes a lot of chrome crashes
      if (process.env.INTERCEPT) {
        await page.setRequestInterception(true);

        page.on('request', (interceptedRequest) => {
          if (interceptedRequest.url.match(/\.(png|jpe?g|mp\d|gif)$/)) {
            interceptedRequest.abort();
          } else {
            interceptedRequest.continue();
          }
        });
      }

      return new Browser(page);
    },
    destroy() {
      return browser.close();
    },
  };

  const pool = genericPool.createPool(factory, { min, max });

  pool.kill = async () => {
    try {
      console.log('draining client connections');
      await pool.drain();
      console.log('closing browser');
      await browser.close();
    } catch(e) {
      console.log('error killing', e);
    }
  };

  return pool;
};

module.exports = instantiatePool;
