var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
/// <reference path="IProxy.ts" />
/// <reference path="../../util/Json.ts" />
/// <reference path="../../util/DateUtils.ts" />
/// <reference path="../../util/ZeroGapUtil.ts" />
/// <reference path="../../ajax/Ajax.ts" />
/// <reference path="../Request.ts" />
/// <reference path="../history/VisitorHistory.ts" />
/// <reference path="../event/ProductViewEvent.ts" />
/// <reference path="../response/Response.ts" />
var econda;
(function (econda) {
    var recengine;
    (function (recengine) {
        var proxy;
        (function (proxy) {
            var Response = econda.recengine.response.Response;
            var ProductViewEvent = econda.recengine.event.ProductViewEvent;
            var DateUtils = econda.util.DateUtils;
            var ZeroGapUtil = econda.util.ZeroGapUtil;
            /**
             * Proxy to send requests to cross sell v1 recommendation service. This is an internal class an there's no reason
             * to use this class directly.
             * @class econda.recengine.proxy.AjaxProxy
             */
            var AjaxProxy = (function (_super) {
                __extends(AjaxProxy, _super);
                function AjaxProxy(cfg) {
                    if (cfg === void 0) { cfg = null; }
                    _super.call(this);
                    /**
                     * Service uri. Used for unit tests only
                     * @cfg {String} uri
                     * @accessor
                     */
                    this.uri = null;
                    /**
                     * Reference to request object
                     * @cfg {econda.recengine.Request} request
                     * @accessor
                     */
                    this.request = null;
                    /**
                     * Last ajax request object. We use this for unit testing.
                     * @private
                     * @property {econda.ajax.Request}
                     */
                    this._ajaxRequest = null;
                    if (cfg instanceof AjaxProxy) {
                        return cfg;
                    }
                    this.initConfig(cfg);
                }
                AjaxProxy.prototype.getUri = function () {
                    return this.uri;
                };
                AjaxProxy.prototype.setUri = function (uri) {
                    this.uri = uri;
                };
                AjaxProxy.prototype.setRequest = function (request) {
                    this.request = request;
                };
                AjaxProxy.prototype.getRequest = function () {
                    return this.request;
                };
                /**
                 * Get instance of the ajax request class that was used to perform the request.
                 * @returns {econda.ajax.Request}
                 */
                AjaxProxy.prototype.getAjaxRequest = function () {
                    return this._ajaxRequest;
                };
                /**
                 * @private
                 * @return {string} protocol to use
                 */
                AjaxProxy.detectProtocol = function () {
                    return (typeof location.protocol === 'string' && location.protocol === 'https:') ? 'https' : 'http';
                };
                /**
                 * Detects if cookies are required for current request.
                 * @returns {Boolean}
                 * @private
                 */
                AjaxProxy.prototype._isCookieRequired = function () {
                    var cookieRequired = false;
                    cookieRequired = cookieRequired || this.request.getAutoContext();
                    return cookieRequired;
                };
                /**
                 * Send request and call {@link #handleSuccess} when done.
                 */
                AjaxProxy.prototype.send = function () {
                    var req = this.request;
                    var cmp = this;
                    var protocol = AjaxProxy.detectProtocol();
                    var uri = this.uri;
                    if (!uri) {
                        uri = [protocol, '://widgets.crosssell.info/eps/crosssell/recommendations/', req.getAccountId(), '.do'].join('');
                    }
                    var params = this.getRecommendationServiceFormFieldParametersFromRequest();
                    var request = this._ajaxRequest = econda.ajax.Ajax.createRequest({
                        uri: uri,
                        method: 'post',
                        writer: 'form-encoded',
                        reader: 'json',
                        data: params,
                        withCredentials: cmp._isCookieRequired(),
                        timeoutMilliseconds: req.getTimeoutMilliseconds(),
                        success: function (ajaxResponse) {
                            cmp.handleSuccess(ajaxResponse);
                        },
                        error: function () {
                            cmp.handleError();
                        }
                    });
                    request.init();
                    if (request.isSupportedRequest()) {
                        request.send();
                    }
                    else {
                        var request = this._ajaxRequest = econda.ajax.Ajax.createRequest({
                            uri: uri,
                            method: 'get',
                            reader: 'json',
                            params: params,
                            withCredentials: cmp._isCookieRequired(),
                            timeoutMilliseconds: req.getTimeoutMilliseconds(),
                            success: function (ajaxResponse) {
                                cmp.handleSuccess(ajaxResponse);
                            },
                            error: function () {
                                cmp.handleError();
                            }
                        });
                        request.send();
                    }
                };
                AjaxProxy.prototype.handleError = function () {
                    var response = new Response({
                        isError: true
                    });
                    this.request.handleResponse(response);
                };
                /**
                 * Handles ajax response data, creates Response object and calls callback on Request object
                 * @private
                 */
                AjaxProxy.prototype.handleSuccess = function (responseData) {
                    if (!responseData) {
                        this.handleError();
                        return;
                    }
                    // modify response data to match expected property names
                    if (typeof responseData.products === 'undefined') {
                        responseData.products = responseData.items || [];
                        delete responseData.items;
                    }
                    if (typeof responseData.widgetdetails !== 'undefined') {
                        responseData.widgetDetails = responseData.widgetdetails;
                        delete responseData.widgetdetails;
                    }
                    if (typeof responseData.start !== 'undefined') {
                        responseData.startIndex = responseData.start;
                        delete responseData.start;
                    }
                    if (typeof responseData.end !== 'undefined') {
                        responseData.endIndex = responseData.end;
                        delete responseData.end;
                    }
                    // remove unused data
                    delete responseData.size;
                    // create response object
                    var response = new Response(responseData);
                    response.setRequest(this.getRequest());
                    this.request.handleResponse(response);
                };
                AjaxProxy.prototype.getRecommendationServiceFormFieldParametersFromRequest = function () {
                    var request = this.request;
                    var params = {};
                    // basics
                    params['wid'] = request.getWidgetId();
                    params['aid'] = request.getAccountId();
                    params['type'] = request.getType();
                    params['start'] = request.getStartIndex();
                    params['widgetdetails'] = true;
                    var csize = request.getChunkSize();
                    if (csize) {
                        params['csize'] = csize;
                    }
                    var productIds = [];
                    if (request.getAutoContext()) {
                        productIds = this._getAutoContextParamValue();
                    }
                    // manual context
                    var context = request.getContext();
                    if (context) {
                        var products = context.getProducts();
                        for (var n = 0; n < products.length; n++) {
                            if (products[n].getSku()) {
                                productIds.push('sku:' + products[n].getSku());
                            }
                            else {
                                productIds.push(products[n].getId());
                            }
                        }
                        context.addToRequest(params);
                        // append history from profile
                        ZeroGapUtil.appendHistoryFromProfile(params);
                        // append current date (see MON-4036)
                        params['timestamp'] = this._currentDateAsUtcIsoString();
                        // handle products excluded
                        var productsExcluded = context.getProductsExcluded();
                        params['excl'] = this._convertProductReferencesListToParamValue(productsExcluded);
                    }
                    params['pid'] = productIds;
                    return params;
                };
                /**
                 * legacy: send list of last viewed products if autoContext is set.
                 * @private
                 */
                AjaxProxy.prototype._getAutoContextParamValue = function () {
                    var productIds = [];
                    var productViewedEvents = econda.data.visitor.getHistory()
                        .getFilteredItems(function (e) { return e instanceof ProductViewEvent; });
                    var productReference;
                    for (var n = 0; n < productViewedEvents.length; n++) {
                        if (productReference = productViewedEvents[n].getProduct()) {
                            if (productReference.getSku()) {
                                productIds.push('sku:' + productReference.getSku());
                            }
                            else {
                                productIds.push(productReference.getId());
                            }
                        }
                    }
                    return productIds.slice(-5).reverse();
                };
                AjaxProxy.prototype._currentDateAsUtcIsoString = function () {
                    return DateUtils.toUtcIsoString(new Date());
                };
                AjaxProxy.prototype._convertProductReferencesListToParamValue = function (productReferences, readerFunction) {
                    var productIds = [];
                    var read = typeof readerFunction === 'function' ? readerFunction : function (item) { return item; };
                    for (var i = 0; i < productReferences.length; i++) {
                        // noinspection TypeScriptValidateTypes
                        var productReference = read(productReferences[i]);
                        if (productReference.getSku() !== null) {
                            productIds.push('sku:' + productReference.getSku());
                        }
                        else {
                            productIds.push(productReference.getId());
                        }
                    }
                    return productIds;
                };
                return AjaxProxy;
            }(econda.base.BaseClass));
            proxy.AjaxProxy = AjaxProxy;
        })(proxy = recengine.proxy || (recengine.proxy = {}));
    })(recengine = econda.recengine || (econda.recengine = {}));
})(econda || (econda = {}));