// This script assumes the following:
//   1. You've installed wd with `npm install wd'.
//   2. You've set the environment variables $SAUCE_USERNAME and $SAUCE_ACCESS_KEY.
//   3. If the environment variable $CIRCLE_ARTIFACTS is not set images will be saved in /tmp
//
// This scripts creates following files for each browser in browserVersions:
//    $CIRCLE_ARTIFACTS/imgs/{browser_version_platform}/#.png
//
// The intention of this script is that it will be ran from CircleCI
//
// Example usage:
//   node screenshots.js http://localhost:9292/test/visual.html
//   node screenshots.js http://google.com

var wd = require('wd');
var fs = require('fs');
var url = process.argv[2];
var username = process.env.SAUCE_USERNAME;
var accessKey = process.env.SAUCE_ACCESS_KEY;
var build_name = process.env.MQ_CI_BUILD_NAME;
var baseDir = process.env.CIRCLE_ARTIFACTS;
if (!baseDir) {
  console.error('No $CIRCLE_ARTIFACTS found, for testing do something like `CIRCLE_ARTIFACTS=/tmp script/screenshots.js`');
  process.exit(1);
}
fs.mkdirSync(baseDir+'/imgs');
fs.mkdirSync(baseDir+'/imgs/pieces');
fs.mkdirSync(baseDir+'/browser_logs');

var browsers = [
  {
    config: {
      browserName: 'Internet Explorer',
      platform: 'Windows XP'
    },
    pinned: true // assume pinned to IE 8
  },
  {
    config: {
      browserName: 'Internet Explorer',
      platform: 'Windows 7'
    },
    pinned: true // assume pinned to IE 11
  },
  {
    config: {
      browserName: 'MicrosoftEdge',
      platform: 'Windows 10'
    }
  },
  {
    config: {
      browserName: 'Firefox',
      platform: 'OS X 10.11'
    }
  },
  {
    config: {
      browserName: 'Safari',
      platform: 'OS X 10.11'
    }
  },
  {
    config: {
      browserName: 'Chrome',
      platform: 'OS X 10.11'
    }
  },
  {
    config: {
      browserName: 'Firefox',
      platform: 'Linux'
    }
  }
];


browsers.forEach(function(browser) {
  browser.config.build = build_name;
  browser.config.name = 'Visual tests, ' + browser.config.browserName + ' on ' + browser.config.platform;
  browser.config.customData = {build_url: process.env.CIRCLE_BUILD_URL};
  var browserDriver = wd.promiseChainRemote('ondemand.saucelabs.com', 80, username, accessKey);
  return browserDriver.init(browser.config)
  .then(function(args) {
    var cfg = browser.config, capabilities = args[1];
    var version = capabilities.version || capabilities.browserVersion;
    var sessionName = [cfg.browserName, version, cfg.platform].join(' ');
    if (capabilities.platformVersion) sessionName += ' ' + capabilities.platformVersion;
    console.log(sessionName, 'init', args);

    var evergreen = browser.pinned ? '' : '_(evergreen)';
    var fileName = [cfg.browserName, version + evergreen, cfg.platform].join('_');
    if (capabilities.platformVersion) fileName += ' ' + capabilities.platformVersion;
    fileName = fileName.replace(/ /g, '_');

    return browserDriver.get(url)
    .then(willLog(sessionName, 'get'))
    .safeExecute('document.body.focus()') // blur anything that's auto-focused
    .then(willLog(sessionName, 'document.body.focus()'))
    .safeExecute('document.documentElement.style.overflow = "hidden"') // hide scrollbars
    .then(willLog(sessionName, 'hide scrollbars'))
    .then(function() {
      // Microsoft Edge starts out with illegally big window: https://git.io/vD63O
      if (cfg.browserName === 'MicrosoftEdge') {
        return browserDriver.getWindowSize()
        .then(function(size) {
          return browserDriver.setWindowSize(size.width, size.height)
        })
        .then(willLog(sessionName, 'reset window size (Edge-only workaround)'))
      }
    })
    .then(function() {
      return [browserDriver.safeExecute('document.documentElement.scrollHeight'),
              browserDriver.safeExecute('document.documentElement.clientHeight')];
    })
    .spread(function(scrollHeight, viewportHeight) {
      console.log(sessionName, 'get scrollHeight, clientHeight', scrollHeight, viewportHeight);

      // the easy case: Firefox and IE return a screenshot of the entire webpage
      if (cfg.browserName === 'Firefox' || cfg.browserName === 'Internet Explorer') {
        return browserDriver.saveScreenshot(baseDir + '/imgs/' + fileName + '.png')
        .then(willLog(sessionName, 'saveScreenshot'))
      // the hard case: for Chrome, Safari, and Edge, scroll through the page and
      // take screenshots of each piece; circle.yml will stitch them together
      } else {
        var piecesDir = baseDir + '/imgs/pieces/' + fileName + '/';
        fs.mkdirSync(piecesDir);

        var scrollTop = 0;
        var index = 1;

        return (function loop() {
          return browserDriver.safeEval('window.scrollTo(0,'+scrollTop+');')
          .then(willLog(sessionName, 'scrollTo()'))
          .saveScreenshot(piecesDir + index + '.png')
          .then(function() {
            console.log(sessionName, 'saveScreenshot');

            scrollTop += viewportHeight;
            index += 1;

            // if the viewport hasn't passed the bottom edge of the page yet,
            // scroll down and take another screenshot
            if (scrollTop + viewportHeight <= scrollHeight) {
              // Use `window.scrollTo` because thats what jQuery does:
              //   https://github.com/jquery/jquery/blob/1.12.3/src/offset.js#L186
              // Use `window.scrollTo` instead of jQuery because jQuery was
              // causing a stackoverflow in Safari.
              return loop();
            } else { // we are past the bottom edge of the page, reduce window size to
              // fit only the part of the page that hasn't been screenshotted.

              // If there is no remaining part of the page, we're done, short-circuit
              if (scrollTop === scrollHeight) return browserDriver;

              return browserDriver.getWindowSize()
              .then(function(windowSize) {
                console.log(sessionName, 'getWindowSize');
                // window size is a little bigger than the viewport because of address
                // bar and scrollbars and stuff
                var windowPadding = windowSize.height - viewportHeight;
                var newWindowHeight = scrollHeight - scrollTop + windowPadding;
                return browserDriver.setWindowSize(windowSize.width, newWindowHeight)
                .then(willLog(sessionName, 'setWindowSize'))
                .safeEval('window.scrollTo(0,'+scrollHeight+');')
                .then(willLog(sessionName, 'scrollTo() Final'))
                .saveScreenshot(piecesDir + index + '.png')
                .then(willLog(sessionName, 'saveScreenshot Final'));
              });
            }
          });
        }());
      }
    })
    .then(function() {
      return browserDriver.log('browser')
      .then(function(logs) {
        var logfile = baseDir + '/browser_logs/' + sessionName.replace(/ /g, '_') + '.log';
        return new Promise(function(resolve, reject) {
          fs.writeFile(logfile, JSON.stringify(logs, null, 2), function(err) {
            err ? reject(err) : resolve();
          });
        })
        .then(willLog(sessionName, 'writeFile'));
      }, function(err) {
        // the Edge, IE, and Firefox-on-macOS drivers don't support logs, but the others do
        console.log(sessionName, 'Error fetching logs:', JSON.stringify(err, null, 2));
      });
    });
  })
  .sauceJobStatus(true)
  .fail(function(err) {
    console.log('ERROR:', browser.config.browserName, browser.config.platform);
    console.log(JSON.stringify(err, null, 2));
  })
  .quit();

  function willLog() {
    var msg = [].join.call(arguments, ' ');
    return function(value) {
      console.log(msg);
      return value;
    };
  }
});
