var async = require('asyncawait/async');
var await = require('asyncawait/await');
var Config = require('./config');
var Promise = require('bluebird');
var mongodb = Promise.promisifyAll(require('mongodb'));
var Log = require('winston');
var sprintf = require('sprintf');
var moment = require('moment');
var URI = require('URIjs');
var MongoClient = mongodb.MongoClient;
var Collection = mongodb.Collection;
var request = Promise.promisifyAll(require('request'));

Log.remove(Log.transports.Console);
Log.add(Log.transports.Console, { timestamp: function() { return moment().format(); } });

function sleep(duration) {
  return new Promise(function(resolve, reject) {
    setTimeout(resolve, duration);
  });
}

function Twitch() {
}

Twitch.request = async(function(url, headers) {
  var tries = 0;
  var maxTries = 5;

  var options = { 'url': url };

  if (headers !== false) {
    options['headers'] = {
      'Accept': 'application/vnd.twitchtv.v3+json',
      'Client-ID': 'nazgul (https://github.com/schmich/nazgul)'
    };
  }

  while (true) {
    ++tries;

    Log.info(sprintf('Requesting %s.', options.url));

    var response = await(request.getAsync(options));
    var body = response[0].body;

    var statusCode = response[0].statusCode;
    Log.info(sprintf('Response status: %d.', statusCode));

    if (statusCode != 200) {
      Log.error(sprintf('Unexpected status code: %d\nResponse: %s', statusCode, body));
      if (tries == maxTries) {
        throw new Error(sprintf('Max tries exceeded for %s.', options.url));
      }

      Log.info(sprintf('Try %d of %d, waiting for 5s.', tries, maxTries));
      await(sleep(5000));
      continue;
    }

    await(sleep(1000));
    
    return JSON.parse(body);
  }
});

module.exports = {
  async: async,
  await: await,
  Config: Config,
  request: request,
  Log: Log,
  sprintf: sprintf,
  URI: URI,
  MongoClient: MongoClient,
  Twitch: Twitch,
  sleep: sleep
};

@@ -834,19 +834,47 @@
  = %7B
+%0A   
  
-'
 url
-'
 : url
+,%0A    timeout: 10 * 1000%0A 
  %7D;%0A
@@ -916,19 +916,16 @@
 ions
-%5B'
+.
 headers
-'%5D
  = %7B
@@ -935,16 +935,14 @@
     
-'
 Accept
-'
 : 'a
@@ -1133,24 +1133,61 @@
 ons.url));%0A%0A
+    var success = false;%0A    try %7B%0A  
     var resp
@@ -1227,24 +1227,26 @@
 ions));%0A    
+  
 var body = r
@@ -1263,16 +1263,18 @@
 .body;%0A%0A
+  
     var 
@@ -1310,24 +1310,26 @@
 usCode;%0A    
+  
 Log.info(spr
@@ -1375,15 +1375,23 @@
 ));%0A
-%0A
+  
     
-if
+success =
  (st
@@ -1403,15 +1403,32 @@
 ode 
-!
+=
 = 200)
+;%0A    %7D catch (e)
  %7B%0A 
@@ -1446,77 +1446,125 @@
 ror(
-sprintf('Unexpected status code: %25d%5CnResponse: %25s', statusCode, body)
+'Error during request.');%0A      Log.error(e.toString());%0A    %7D%0A%0A    if (!success) %7B%0A      Log.error('Request failed.'
 );%0A 

Set 10 second timeout on all Twitch requests to prevent hangs.