/**
* HTTP Client using the JSGI standard objects
*/
var defer = require("../../promise").defer,
	when = require("../../promise").when,
	LazyArray = require("../../lazy-array").LazyArray,
	http = require("http"),
	https = require("https"),
	parse = require("url").parse;

// configurable proxy server setting, defaults to http_proxy env var
exports.proxyServer = require("../../process").env.http_proxy;

exports.request = function(originalRequest){
	// make a shallow copy of original request object
	var request = {};
	for(var key in originalRequest){
		if(originalRequest.hasOwnProperty(key)){
			request[key] = originalRequest[key];
		}
	}

	if(request.timeout === undefined)request.timeout= 20000; // default timeout.
	if(request.url){
		var parsed = parse(request.url);
		if (parsed.pathname) {
			parsed.pathInfo = parsed.pathname;
		} else {
			parsed.pathInfo = "/";
		}
		request.queryString = parsed.query || "";
		for(var i in parsed){
			request[i] = parsed[i];
		}
	}
	var deferred = defer();
	if(exports.proxyServer){
		request.pathname = request.url;
		var proxySettings = parse(exports.proxyServer);
		request.port = proxySettings.port;
		request.protocol = proxySettings.protocol;
		request.hostname = proxySettings.hostname;
	}
	if(!request.protocol){
		throw new Error("No valid protocol/URL provided");
	}
	var timedOut, bodyDeferred;
	// Limits the time of sending the request + receiving the response header to 20 seconds.
	// No timeout is used on the client stream, but we do destroy the stream if a timeout is reached.
	var timeout = setTimeout(function(){
		timedOut = true;
		req.destroy();
		deferred.reject(new Error("Timeout"));
	}, request.timeout);

	var secure = request.protocol.indexOf("s") > -1;
	request.port = request.port || (secure ? 443 : 80);
	request.headers = request.headers || {host: request.host || request.hostname + (request.port ? ":" + request.port : "")};
	request.host = request.hostname;
	request.method = request.method || "GET";
	request.path = request.pathname || request.pathInfo || "";
	if (request.queryString) {
		request.path += "?"+request.queryString;
	}
	var timedOut;

	var req = (secure ? https : http).request(request);
	req.on("response", function (response){
		if(timedOut){
			return;
		}
		response.status = response.statusCode;
		var sendData = function(block){
			buffer.push(block);
		};
		var buffer = [];
		bodyDeferred = defer();
		var body = response.body = LazyArray({
			some: function(callback){
				buffer.forEach(callback);
				sendData = callback;
				return bodyDeferred.promise;
			}
		});
		response.setEncoding(request.encoding || "utf8");

		response.on("data", function (chunk) {
			sendData(chunk);
		});
		response.on("end", function(){
			bodyDeferred.resolve();
		});
		deferred.resolve(response);
		clearTimeout(timeout);
	});
	req.on('error', function(e) {
		if (!timedOut) {
            deferred.reject(e);
            clearTimeout(timeout);
        }
	});
	if(request.body){
		return when(request.body.forEach(function(block){
			req.write(block);
		}), function(){
			req.end();
			return deferred.promise;
		});
	}else{
		req.end();
		return deferred.promise;
	}
};
