/**
 * @module request
 *
 * @description Jsonp requests on client normal http requests on server.
 */
/*!
 * @TODO: what about normal ajax requests on client ?
 */

var _ = require('lodash');
var UAParser = require('ua-parser-js');

module.exports = typeof window == 'undefined' ? serverRequest : clientRequest;

/**
 * Враппер для jQuery.ajax и request с более менее общим апи.
 *
 * Из параметров ниже, `xhr` и `errorDesc` зависит от среды исполнения.
 *
 * @param {string} conf.url - Урл запроса.
 * @param {string} conf.type - Тип запроса (на сервере поддерживается только json).
 * @param {Object} conf.data - Параметры запроса.
 * @param {Function} [conf.success] - callback(body, xhr)
 * @param {Function} [conf.error] - callback(xhr, reason)
 * @param {Function} [conf.complete] - callback(error, result, xhr)
 * @param {int} conf.timeout - In milliseconds.
 * @returns {*}
 */
function serverRequest(conf) {
    var request = require('request'),
        winston = require('./logger');

    if (conf.method && conf.method.toLowerCase() == 'post') {
        conf.form = conf.data;
    } else {
        conf.qs = conf.data;
    }

    _.defaults(conf, {
        success: _.noop,
        error: _.noop,
        complete: _.noop,
        pool: false
    });

    // @doclink: https://github.com/mikeal/request#requestoptions-callback
    return request(conf, function(error, xhr, body) {
        if (error) {
            conf.error.call(conf.context, xhr, error);

            winston.error("Couldn't do request", {
                url: conf.url,
                params: conf,
                statusCode: xhr && xhr.statusCode,
                error: error + ''
            });
        } else {
            try {
                body = conf.type.match(/^json/) ? JSON.parse(body) : body;
                conf.success.call(conf.context, body, xhr);
            } catch (ex) {
                if (ex instanceof SyntaxError) {
                    var err = new SyntaxError(
                        "[request] couldn't parse response as JSON (from " + conf.url + "): " + body
                    );

                    conf.error.call(conf.context, xhr, err);
                } else {
                    throw ex;
                }
            }
        }

        conf.complete.call(conf.context, error, body, xhr);
    });
}


var isLegacyIECached = null;

function isLegacyIE() {
    if (isLegacyIECached == null) {
        var res = UAParser(navigator.userAgent);
        isLegacyIECached = res.browser.name == 'IE' && Number(res.browser.major) < 10;
    }
    return isLegacyIECached;
}

var originRe = /(?:https?:\/\/|\/)?([^/:]+)/;

function isSameOrigin(url) {
    var matched = url.match(originRe);
    if (matched) {
        return document.location.hostname == matched[1];
    }
}

function clientRequest(conf) {
    var reqwest = require('reqwest');
    // @doclink: https://github.com/ded/reqwest

    _.defaults(conf, {
        success: _.noop,
        error: _.noop,
        complete: _.noop,
        overrideType: _.noop
    });

    if (!isSameOrigin(conf.url)) {
        conf.crossOrigin = true;
    }

    // IE ниже 10 версии не поддерживают передачу кук в кросс-доменных сценариях
    if (conf.crossOrigin && conf.withCredentials && conf.type != 'jsonp' && isLegacyIE()) {
        conf.type = 'jsonp';
        conf.overrideType('jsonp');
    }

    var xhr = reqwest(conf);

    // во время аборта запроса не логируем его как ошибку
    var abort = xhr.abort;
    xhr.abort = function() {
        conf.error = _.noop;
        abort.call(xhr);
    };

    return xhr;
}

@@ -2609,11 +2609,8 @@
  = /
-(?:
 http
@@ -2620,13 +2620,8 @@
 %5C/%5C/
-%7C%5C/)?
 (%5B%5E/
@@ -2639,20 +2639,21 @@
 ction is
-Same
+Cross
 Origin(u
@@ -2758,17 +2758,17 @@
 ostname 
-=
+!
 = matche
@@ -3047,15 +3047,15 @@
 if (
-!
 is
-Same
+Cross
 Orig

fix lib/request again