'use strict';

var Promise = require('bluebird');

var webdriver = require('selenium-webdriver');

var consts = require('../constants');

function normalizeUrl(url) {
  if (!/^\w+?:\/\//.test(url)) {
    url = 'http://' + url;
  }
  return url;
}

function open(browserName, serverUrl) {
  // haven't tested on ie. Safari is buggy (can't receive sent keys correctly)
  // http://stackoverflow.com/questions/18389419/selenium-webdriverjs-cannot-
  // build-webdriver-for-chrome
  if (browserName !== 'firefox' && browserName !== 'chrome') {
    return new Error('Unsupported browser.');
  }

  var browser;
  if (browserName === 'firefox') {
    browser = webdriver.Capabilities.firefox();
    serverUrl = serverUrl || consts.DEFAULT_SERVER_URL_FIREFOX;
  } else {
    // https://code.google.com/p/chromedriver/issues/detail?id=799
    // need to pass this arg, or else the chrome window displays an error
    // banner message, which screws up viewport dimensions
    browser = webdriver.Capabilities.chrome().set('chromeOptions', {
      args: ['--test-type'],
    });
    serverUrl = serverUrl || consts.DEFAULT_SERVER_URL_CHROME;
  }

  var driver = new webdriver.Builder()
    .usingServer(serverUrl)
    .withCapabilities(browser)
    .build();

  if (driver == null) {
    return new Error('Unsupported browser driver.');
  }

  return driver;
}

// selenium amuses itself by implementing promises themselves, and very poorly.
// Beside the basic `then`, there isn't much else. Here I wrap their pseudo-
// promises with the actually good implementation from bluebird, so that things
// like `finally` and `all` work. Plus, lots of these need normalization anyways

// `bluebird.promisifyAll` won't work here for various reasons, e.g. the
// `driver.manage().moreBla` right below

// (w, h) is the size of the browser content dimensions, which is what we want
// most of the times. Selenium's `setSize`, however, asks for whole browser size
// including browser chrome height. Normalize all here.

var browserChrome = {
  'chrome': [0, 72],
  'firefox': [0, 106],
};

function setSize(driver, browserName, w, h) {
  var displayW = w + browserChrome[browserName][0];
  var displayH = h + browserChrome[browserName][1];

  var prom = new Promise(function(resolve, reject) {
    driver.manage().window().setSize(displayW, displayH).then(resolve, reject);
  });
  return prom;
}

function takeScreenshot(driver) {
  var prom = new Promise(function(resolve, reject) {
    driver.takeScreenshot().then(resolve, reject);
  });
  return prom;
}

// useful for getting the browser name of the injected driver
function getBrowserName(driver) {
  var prom = new Promise(function(resolve, reject) {
    driver
      .getCapabilities()
      .then(function(whatIsThis) {
        // damn it selenium, where's the js api docs
        var browserName = whatIsThis.caps_.browserName;
        resolve(browserName);
      }, reject);
  });
  return prom;
}

function goToUrl(driver, url) {
  var prom = new Promise(function(resolve, reject) {
    driver.get(normalizeUrl(url))
      .then(function() {
        // wow selenium
        // right now the url bar has focus. So if you try to programmatically
        // focus an html node it'd fail. Bring the focus back
        return executeScript(driver, 'window.focus();');
      })
      .then(resolve, reject);
  });
  return prom;
}

function executeScript(driver, script) {
  // this is the only method where we expose selenium Promises rather than
  // bluebird's: https://github.com/petkaantonov/bluebird/wiki/Error:-circular-
  // promise-resolution-chain

  // executeScript has to return the return of your js script. This screws
  // things up since all the other bluebird wrappers up and below return selves

  // this can pollute the whole system. Fortunately, in every case where
  // executeScript is used, we never return the same chained promise. So further
  // down the line we still get bluebird's clean promises (which is the whole)
  // point of these wrapping
  return driver.executeScript(script);
}

function quit(driver) {
  var prom = new Promise(function(resolve, reject) {
    driver.quit().then(resolve, reject);
  });
  return prom;
}

module.exports = {
  executeScript: executeScript,
  getBrowserName: getBrowserName,
  goToUrl: goToUrl,
  open: open,
  quit: quit,
  setSize: setSize,
  takeScreenshot: takeScreenshot,
};

@@ -2743,25 +2743,18 @@
 unction(
-whatIsThi
+re
 s) %7B%0A   
@@ -2833,17 +2833,22 @@
 e = 
-whatIsThi
+res.caps_ ? re
 s.ca
@@ -2862,17 +2862,41 @@
 wserName
-;
+ : res.get('browserName')
 %0A       

fix chrome bug in getBrowserName