argos.require("classes");
argos.require("widgets.quickinfo");


argos.products = new (function() {

	var _classes = {
		Element: argos.classes.Element
	}

	var _helpers = {
		unique : argos.utils.generateUniqueStr
	}
	
	// CLASSES
	function Product($node) {
		// Build an HTML product from xml. Now severaly cut-down because most mark-up in xml, which is just html,
		// due to technical difficulties in getting decent data from backend.
		// This Class may later be extended to allow passing object markup (e.g. JSON) for build parameters and data.
		_classes.Element.call(this, "<dl class=\"product\"></dl>");

		(function _init() {
			var id = $node.attr("id");
			var $title = this.property("title", $node.find(".title"));
			var $number = this.property("number", $node.find(".number"));
			var $price = this.property("price", $node.find(".price"));
			var $image = this.property("image", $node.find(".image"));
			var $rating = this.property("customerrating", $node.find(".customerrating"));
			var location = this.property("location", $node.find("a", $title).attr("href"));

			id = id ? id : _helpers.unique("product_");
			this.$node.attr("id", id);
			this.$node.addClass($node.attr("class"));
			this.property("id", id);

			// Applying catch-all, for now.
			this.$node.append($node.children());
//			this.$node.append($title);
//			this.$node.append($number);
//			this.$node.append($price);
//			this.$node.append($image);
			
		}).apply(this);
	}
	Product.prototype = new _classes.Element();
		
	function Price(data, selectors) {
		var _main = data["main"] ? data.main.trim() : "";
		var _findFigure = /[^\d]*(\d*\.\d{2}).*/;
		var _was = data["was"] ? data.was.trim() : "";
		var _save = data["save"] ? data.save.trim() : "";
		var _symbols = data["symbols"] ? data.symbols : new Array();
		var _addCurrency = "&pound;$1";
		
		this.now = "<span class=\"main\">" + _main.trim().replace(_findFigure, _addCurrency) + "</span>";
		this.symbols = _symbolsToHtml(_symbols);
		this.was = _was ? "<span class=\"wasPrice\">was " + _was.replace(_findFigure, _addCurrency) + "</span>" : "";
		this.save = _save ? "<span class=\"savePrice\">" + _save.replace(_findFigure, _addCurrency) + "</span>" : "";


		function _symbolsToHtml(symbols) {
			var html = "";
			for(var i=0; i<symbols.length; ++i) {
				html += "<img class=\"" + symbols[i]["class"] + "\" src=\"" + symbols[i]["src"] + "\" alt=\"" + symbols[i]["alt"] + "\" />";
			} 
			return html;
		}
	}
	
	function Image(src, href, text) {	
		function _html() {
			return "<img alt=\"" + text + "\" src=\"" + src + "\" />";
		}
		
		this.linkedHtml = function() {
			return "<a href=\"" + href + "\" title=\"more details on " + text + "\">" + _html() + "</a>";
		}
		
		this.html = _html;
	}
	
	
	// PUBLIC:
	this.classes = {};
	this.classes.Product = Product;
	
});

// Custom sorting functions for Argos products.
argos.products.sorting = {
	titleAToZ : function(a, b) {
		var titleA = $(a).find(".title").text();
		var titleB = $(b).find(".title").text();
		if(titleA < titleB) return -1;
		if(titleA == titleB) return 0;
		if(titleA > titleB) return 1;
	},

	priceLowToHigh : function(a, b) {
		// If the product has .price .main stucture, that's what we want. Else, just try getting price from dd.price
		var priceA = parseFloat($(a).find(".price .main, dd.price").text().replace(/[£|&pound;|\s]/mg, ""));
		var priceB = parseFloat($(b).find(".price .main, dd.price").text().replace(/[£|&pound;|\s]/mg, ""));
		priceA = priceA.slice(0, priceA.indexOf(".") + 3);
		priceB = priceB.slice(0, priceB.indexOf(".") + 3);
		if(priceA < priceB) return -1;
		if(priceA > priceB) return 1;
		if(priceA == priceB || isNaN(priceA) || isNaN(priceB)) return 0;
	},

	ratingHighToLow : function(a, b) {
		var ratingA = Number($(a).find(".rating").text());
		var ratingB = Number($(b).find(".rating").text());
		if(ratingA > ratingB) return -1;
		if(ratingA == ratingB) return 0;
		if(ratingA < ratingB) return 1;
	},

	reversed : function(a, b) {
		// This doesn't work in IE. Use Array.reverse() if possible.
		return 1;
	}
}

argos.products.components = new(function(){

	var _classes = {
		Collection: argos.classes.Collection
	}


	// this is populated page builds (see method below)									
	var _containersProductComponentLimit = [];
	
	// methods called as page builds
	this.setContainerProductComponentLimit = function(selector,maxlimit) {
		_containersProductComponentLimit.push([selector,maxlimit]);
	}
		
	// this method is used to examine list of containers we are working with
	this.checkContainerProductComponentLimit = function(selector) {
		var result = false;
		$(_containersProductComponentLimit).each(function () {
            if (this[0] == selector) {
            	result = true;
            }
        });
		return result;
	}
	
	this.getProductComponentsByArray = function(partnumbers,selector,viewname,options) {
		var url = "/webapp/wcs/stores/servlet/"+viewname;	
		var data = "storeId=10001&langId=-1";
		// by individual partNumbers
		//	data += "&partNumber=" + partnumbers.join("&partNumber=");
		// using CSV format to ensure correct return order
		data += "&partNumberCsv="+partnumbers.join(",");
		$.ajax({
			url: url,
			dataType: "html",
			type: "get",
			data: data,
			success: function(html){
				_insertProductComponents(html,selector,options);
			},
			error: function(){
				// if getter fails, just return out
				return;
			}
		});
	}

	function _insertProductComponents(html,selector,options) {
			
		var config = {
			quicklink : false,
			appendFunction : null,
			preAppendFunction : null,
			postAppendFunction : null,
			trackingCode : null
		}
	
		if(typeof options === "object"){
			config.quicklink = (typeof options.quicklink === "boolean") ? options.quicklink : config.quicklink;
			config.appendFunction = (typeof options.appendFunction=== "function") ? options.appendFunction : config.appendFunction;
			config.preAppendFunction = (typeof options.preAppendFunction=== "function") ? options.preAppendFunction : config.preAppendFunction;
			config.postAppendFunction = (typeof options.postAppendFunction=== "function") ? options.postAppendFunction : config.postAppendFunction;
			config.trackingCode = (typeof options.trackingCode=== "string") ? options.trackingCode : config.trackingCode;
		}

		if(html.length) {			
			var c = $(selector);
			var preFncs = preFncs || null;
			var postFncs = postFncs || null;
			var appendFncs = appendFncs || null;
			// wrap the supplied products to ensure find operation works
			var h = $("<div class='products' />").append(html);
			var hProducts = h.find("dl.product");
	
		
		
			var productsToAppend = new _classes.Collection();
			
			// run pre functions 
			_runAppendAndPrePostFunctions(config.preAppendFunction(selector));
			// if we have valid products and container is in place then proceed
			var productsToAdd = _calculateProductsToAdd(hProducts.length,selector);
			if(productsToAdd>0){
				// push up to allowed number of products
				for(var i=0; i < productsToAdd; i++) {
					if(config.quicklink){
						argos.widgets.quickinfo.postLoadAddition($(hProducts[i]));
					
					}
					
					productsToAppend = productsToAppend.add(hProducts[i]);
				}
				if(config.appendFunction){
					//send products back to page specific script for insertion
					_runAppendAndPrePostFunctions(config.appendFunction(selector,productsToAppend));
				} else {
					c.append(productsToAppend);
			}
			
		}
			// run post append functions 
			_runAppendAndPrePostFunctions(config.postAppendFunction(selector,config.trackingCode));		
	}
	}
	
	// allows retrieved products to be added to container if still within MAX_LIMIT
	// will not alter products provided on page load
	function _calculateProductsToAdd(productcount,selector) {
		var existingProducts = $(selector + " .product");
		var productsToAdd = 0;	
		//find MAX_LIMIT for this container
		$(_containersProductComponentLimit).each(function () {
            if (this[0] == selector) {
      //    	alert("!!!"+this[0]+ " max limit is " + this [1] + ", there are " + existingProducts.length + " exisitng products and " + productcount + " from avail");
				//how many have been supplied + exist already... up to the max limit set
				productExcess = parseInt(this[1]) - (existingProducts.length + productcount);
				productsToAdd = (productExcess < 0) ? productcount + productExcess : productcount;
			}
       });
       return productsToAdd
	}	
	
	function _runAppendAndPrePostFunctions(fncs,productsToAppend){
		if(fncs != null){
			$(fncs).each(function () {
				this();
			});
		}
	}
	
	
});



