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="../util/StringUtils.ts" />
/// <reference path="response/Response.ts" />
/// <reference path="decorator/PerformanceTracking.ts" />
/// <reference path="decorator/ProductListRandomizer.ts" />
/// <reference path="../base/BaseClass.ts" />
/// <reference path="context/Context.ts" />
/// <reference path="proxy/AjaxProxy.ts" />
var econda;
(function (econda) {
    var recengine;
    (function (recengine) {
        var Context = econda.recengine.context.Context;
        /**
         * Simple recommendation request to cross sell engine.
         * @class econda.recengine.Request
         * @extends econda.base.BaseClass
         *
         * <h2>Examples</h2>
         *
         * <h3> Send request to econda recommendation service: </h3>
         *     var request = new econda.recengine.Request({
         *         accountId: '00000cec-d98025a8-912b-46a4-a57d-7a691ba7a376-1',
         *         widgetId: 6,
         *         context: {
         *             products: [{id: 'prodId1'}, {id: 'prodId2'}],
         *             categories: [{
         *                 type: 'brand',
         *                 path: 'econda'
         *             }]
         *         }
         *     });
         *     request.send();
         *
         * <h3> Get econda recommendation service properties for shop server side processing: </h3>
         *     var request = new econda.recengine.Request({
         *         accountId: '00000cec-d98025a8-912b-46a4-a57d-7a691ba7a376-1',
         *         widgetId: 6,
         *         context: {
         *             products: [{id: 'prodId1'}, {id: 'prodId2'}],
         *             categories: [{
         *                 type: 'brand',
         *                 path: 'econda'
         *             }]
         *         }
         *     });
         *     var econdaRecoParameters = request.getRecommendationServiceParameters();
         *
         *     // Send econdaRecoParameters to shop for server side processing.
         *     // The parameters have to be passed on to econda recommendation services.
         *
         */
        var Request = (function (_super) {
            __extends(Request, _super);
            function Request(cfg) {
                if (cfg === void 0) { cfg = null; }
                _super.call(this);
                /**
                 * Widget id as defined in cross sell management interface
                 * @cfg {Number} widgetId
                 * @accessor
                 */
                this.widgetId = null;
                /**
                 * Cross Sell account id.
                 * @cfg {String} accountId
                 */
                this.accountId = null;
                /**
                 * Index of first result item. Starts with 0
                 * @cfg {Number} startIndex [Number=0]
                 * @accessor
                 */
                this.startIndex = 0;
                /**
                 * Max. number of results
                 * @cfg {Number} chunkSize
                 * @accessor
                 */
                this.chunkSize = null;
                /**
                 * Context of request.
                 * If defaultContextEnabled is set to true, this function will return this default context on first call.
                 * If set to false, it will return null.
                 *
                 * @cfg {econda.recengine.context.Context} context
                 * @accessor
                 */
                this.context = null;
                /**
                 * True to enable a default context for all requests.
                 * @cfg {boolean} [defaultContextEnabled=true]
                 * @accessor
                 */
                this.defaultContextEnabled = true;
                /**
                 * True to use the last viewed products as request context. See VisitorProfile history for details.
                 * @cfg {Boolean} autoContext
                 * @accessor
                 */
                this.autoContext = false;
                /**
                 * Request type
                 * @cfg {String} [type=cs]
                 */
                this.type = Request.TYPE_CROSS_SELL;
                /**
                 * List of response decorators
                 * @cfg {Array} decorators must implement IResultDecorator interface
                 */
                this.decorators = [];
                /**
                 * Proxy to use for request
                 * @cfg {String} proxy name or instance of IProxy interface
                 * @accessor
                 */
                this.proxy = null;
                /**
                 * Callback handle after successful request.
                 * @cfg {Function} success
                 * @accessor
                 */
                this.success = null;
                /**
                 * Function to call if there was an error during cross Sell ajax request.
                 * @cfg {Function} error
                 * @accessor
                 */
                this._error = null;
                /**
                 * milliseconds till timeout and abort
                 * @cfg {Number} timeoutMilliseconds [Number=0]
                 * @accessor
                 */
                this.timeoutMilliseconds = 0;
                /**
                 * Function to call after request has finished (successful or not)
                 * @cfg {Function} callback
                 * @accessor
                 */
                this._callback = null;
                /**
                 * True if last request was successfull.
                 * @property {Boolean} requestWasSuccessful
                 */
                this.requestWasSuccessful = null;
                if (cfg instanceof Request) {
                    return cfg;
                }
                else {
                    this.initConfig(cfg);
                }
            }
            Request.prototype.getWidgetId = function () {
                return this.widgetId;
            };
            Request.prototype.setWidgetId = function (widgetId) {
                this.widgetId = widgetId;
                return this;
            };
            /**
             * Returns account id or account id of global configuration (econdaConfig.crosssellAccountId) or null if not set.
             * @returns String
             */
            Request.prototype.getAccountId = function () {
                return this.accountId || econdaConfig.crosssellAccountId;
            };
            /**
             * Set account id for this request. Setting Cross Sell accountId on global config
             * (econdaConfig.crosssellAccountId) might be a better place.
             * @param {String} accountId
             * @chainable
             */
            Request.prototype.setAccountId = function (accountId) {
                this.accountId = accountId;
                return this;
            };
            Request.prototype.getStartIndex = function () {
                return this.startIndex;
            };
            Request.prototype.setStartIndex = function (index) {
                this.startIndex = index;
                return this;
            };
            Request.prototype.getChunkSize = function () {
                return this.chunkSize;
            };
            Request.prototype.setChunkSize = function (count) {
                this.chunkSize = count;
                return this;
            };
            Request.prototype.getContext = function () {
                return this.defaultContextEnabled
                    ? this.context || new Context()
                    : this.context;
            };
            Request.prototype.setContext = function (context) {
                this.context = new Context(context);
                return this;
            };
            Request.prototype.getDefaultContextEnabled = function () {
                return this.defaultContextEnabled;
            };
            Request.prototype.setDefaultContextEnabled = function (enabled) {
                this.defaultContextEnabled = (enabled === true);
            };
            Request.prototype.getAutoContext = function () {
                return this.autoContext;
            };
            Request.prototype.setAutoContext = function (autoContext) {
                this.autoContext = autoContext;
                return this;
            };
            Request.prototype.getType = function () {
                return this.type;
            };
            Request.prototype.setType = function (requestType) {
                if (requestType !== Request.TYPE_CROSS_SELL && requestType !== Request.TYPE_AD_REQUEST) {
                    econda.debug.error('Trying to set invalid cross sell request type: ' + requestType);
                }
                this.type = requestType;
                return this;
            };
            Request.prototype.getDecorators = function () {
                return this.decorators;
            };
            Request.prototype.setDecorators = function (decorators) {
                var cmp = this;
                return this.setArray('decorators', decorators, null, {
                    callback: function (dec) {
                        dec.setRequest(cmp);
                    }
                });
            };
            Request.prototype.addDecorators = function (decorators) {
                var cmp = this;
                return this.addArray('decorators', decorators, null, {
                    callback: function (dec) {
                        dec.setRequest(cmp);
                    }
                });
            };
            Request.prototype.getProxy = function () {
                return this.proxy;
            };
            Request.prototype.setProxy = function (proxy) {
                if (typeof proxy === 'string') {
                    var className = econda.util.StringUtils.ucFirst(proxy);
                    if (typeof econda.recengine.proxy[className] !== 'undefined') {
                        this.proxy = new econda.recengine.proxy[className]();
                    }
                    else {
                        throw 'proxy not supported: ' + proxy;
                    }
                }
                else {
                    this.proxy = proxy;
                }
                if (this.proxy && typeof this.proxy.setRequest !== 'undefined') {
                    this.proxy.setRequest(this);
                }
                return this;
            };
            Request.prototype.getSuccess = function () {
                return this.success;
            };
            Request.prototype.setSuccess = function (callback) {
                this.success = callback;
                return this;
            };
            Request.prototype.getError = function () {
                return this._error;
            };
            Request.prototype.setError = function (callback) {
                this._error = callback;
                return this;
            };
            Request.prototype.getTimeoutMilliseconds = function () {
                return this.timeoutMilliseconds;
            };
            Request.prototype.setTimeoutMilliseconds = function (seconds) {
                this.timeoutMilliseconds = seconds;
                return this;
            };
            Request.prototype.getCallback = function () {
                return this._callback;
            };
            Request.prototype.setCallback = function (callback) {
                this._callback = callback;
                return this;
            };
            /**
             * Send request. Set callbacks to handle result.
             */
            Request.prototype.send = function () {
                var proxy = this.proxy;
                if (!proxy) {
                    proxy = new econda.recengine.proxy.AjaxProxy();
                    proxy.setRequest(this);
                }
                this._validateAndLogErrors();
                proxy.send();
            };
            /**
             * Returns recommendation service parameters
             * @returns {Object} parameters as expected by econda recommendation services
             */
            Request.prototype.getRecommendationServiceParameters = function () {
                var proxy = this.proxy;
                if (!proxy) {
                    proxy = new econda.recengine.proxy.AjaxProxy();
                    proxy.setRequest(this);
                }
                return proxy.getRecommendationServiceFormFieldParametersFromRequest();
            };
            /**
             * Log errors to debug
             * @private
             */
            Request.prototype._validateAndLogErrors = function () {
                if (!this.getAccountId()) {
                    econda.debug.error('Missing crosssell account id in request.', this);
                }
                if (!this.getWidgetId()) {
                    econda.debug.error('Missing widget id in request', this);
                }
            };
            /**
             * Handles response from proxy, must be called from proxy class
             * @param {econda.recengine.response.Response} response
             */
            Request.prototype.handleResponse = function (response) {
                if (response.getIsError()) {
                    if (typeof this._error === 'function') {
                        this._error();
                    }
                }
                else {
                    this.processResponseDecorators(response);
                    if (typeof this.success === 'function') {
                        this.success(response);
                    }
                }
                if (typeof this._callback === 'function') {
                    this._callback(response);
                }
            };
            /**
             * Process added decorators, add default decorators
             * @private
             */
            Request.prototype.processResponseDecorators = function (response) {
                // auto add decorators based on response data
                var details = response.getWidgetDetails();
                var tracking = details && details.getTracking();
                if (tracking && tracking.getEmcs() === true) {
                    var source = '';
                    var context = this.getContext();
                    if (context && context.getProducts().length > 0) {
                        source = context.getProducts()[0].getId();
                    }
                    this.addDecorators(new econda.recengine.decorator.PerformanceTracking({
                        position: tracking.getEmcs1(),
                        source: source,
                        widgetName: tracking.getEmcs0()
                    }));
                }
                // each decorator must process each product...
                for (var i = 0; i < this.decorators.length; i++) {
                    this.decorators[i].decorate(response);
                }
            };
            Request.TYPE_CROSS_SELL = 'cs';
            Request.TYPE_AD_REQUEST = 'ac';
            return Request;
        }(econda.base.BaseClass));
        recengine.Request = Request; // end of class
    })(recengine = econda.recengine || (econda.recengine = {}));
})(econda || (econda = {})); // end of module