//<!-- Model-View-Controller for variant selection -->
//<!-- Allows seperation of domain, view and controller -->
//<!-- Controller (VariantSelectionController) manipulates domain model (VariantProduct)
//<!-- the domainmodel raise events (OnVariantChanged), the view is subscribed to the event and updates itself.

//<!-- Variant (Domain) -->
function VariantProduct(productInfo) 
{	
	this.productInfo = productInfo;
	
	this.OnVariantChanged = new EventList();	
	this.OnVariantDimensionChanged = new EventList();
	this.OnQuantityChanged = new EventList();
	
	this.selected = new SelectedValues(0, null, null);
	
	this.SetCurrentVariant = function(variantId) 
	{
		this.selected.variant = null;
		
		if (variantId != null) 
		{
			this.selected.variant = this.productInfo.Variants[variantId];
			
			this.selected.variantDimensions = JSON.parse(JSON.stringify(this.productInfo.Variants[variantId].VariantDimensions));
		}
		
		this.OnVariantChanged.Invoke(new VariantInvoker(this));	
	}
				
	this.SetDimensionValue = function(dimension, value, setByVisualController) {
	
	    this.selected.lastDimensionSet = dimension;
	    
	    this.selected.lastDimensionValueSet = value;
	    
	    this.selected.wasSetByVisualController = eval(setByVisualController);
	
		this.selected.variantDimensions[dimension] = value;
		
		this.SetCurrentVariant(this.FindMatchingVariantId());
		
		this.OnVariantDimensionChanged.Invoke(new VariantDimensionInvoker(this, dimension, value));		
	}
	
	this.SetSelectedQuantity = function(value) {
		this.selected.productQuantity = value;
		
		this.OnQuantityChanged.Invoke(new QuantityInvoker(this, value));		
	}
		
    this.QuantityPersistOnControlLink = function(aControl, url, productLinkID)
    {
        var productLink = document.getElementById(productLinkID);
	    var link = url;
        var queryString = url.replace(/^[^\?]+\??/,'');
        var found = false;

        // Query string present; parse params to check on existence of SelQty param
        if (queryString != null)
        {
            var Pairs = queryString.split(/[;&]/);
            for ( var i = 0; i < Pairs.length; i++ ) 
            {
                var KeyVal = Pairs[i].split('=');
                if ( ! KeyVal || KeyVal.length != 2 ) 
                {
                    continue; // to next param
                }
                
                var key = unescape( KeyVal[0] );
                var val = unescape( KeyVal[1] );

                val = val.replace(/\+/g, ' ');
                
                if (key == 'SelQty')
                {
                    found = true;
                    link = link.replace(key + '=' + val, key + '=' + aControl.value);
                    productLink.href = link;
                    break; // break loop;
                }
            }
        }
        
        // Not found add the param to query
	    if (!found && productLink != null && productLink.href != null && aControl.value != '0')
	    {	
		    link += (url.indexOf('?') > -1 ? '&' : '?') + 'SelQty=' + aControl.value;
	        productLink.href = link;
	    }
    }
    
	this.FindMatchingVariantId = function() 
	{	
	    var dimensionString = JSON.stringify(this.selected.variantDimensions);
		for(cvariantId in productInfo.Variants) 
		{
			var cvariant = productInfo.Variants[cvariantId];
			
			if (JSON.stringify(cvariant.VariantDimensions) == dimensionString) 
			{
			    return cvariantId;
		    }
		}
	}	
}

//<!-- Internal -- >
function SelectedValues(productQuantity, variant, variantDimensions)
{
    // Added this when selected quantity is initialized through query param
    var queryString = document.location.href.replace(/^[^\?]+\??/,'');
    var found = false;
    
    // Query string present; parse params to check on existence of SelQty param
    if (queryString != null)
    {
        var Pairs = queryString.split(/[;&]/);
        for ( var i = 0; i < Pairs.length; i++ ) 
        {
            var KeyVal = Pairs[i].split('=');
            if ( ! KeyVal || KeyVal.length != 2 ) 
            {
                continue; // to next param
            }
            
            var key = unescape( KeyVal[0] );
            var val = unescape( KeyVal[1] );

            val = val.replace(/\+/g, ' ');
            
            if (key == 'SelQty')
            {
               productQuantity = val;
               break;
            }
        }
    }
       
    this.lastDimensionSet = '';
    this.lastDimensionValueSet = '';
    this.wasSetByVisualController = false;    
	this.productQuantity = productQuantity;
	this.variant = variant;
	this.variantDimensions =  variantDimensions;
}

//<!-- EventList -- >
function EventList() {
	this.subscribers = new Array();
	
	this.Add = function(method) {
		this.subscribers[this.subscribers.length] = method;
	}
	
	this.Invoke = function(invoker) {	
		for(var i=0;i<this.subscribers.length;i++) {
			invoker.Invoke(this.subscribers[i]);
		}
	}
}

function VariantInvoker(product) {
	this.product = product;
	
	this.Invoke = function(method) {
		method(this.product);
	}
}

function VariantDimensionInvoker(product, dimension, value) {
	this.product = product;
	this.dimension = dimension;
	this.value = value;
	this.Invoke = function(method) {
		method(this.product, this.dimension, this.value);
	}
}

function QuantityInvoker(product, value) {
    this.product = product;
	this.value = value;
	this.Invoke = function(method) {
		method(this.product, this.value);
	}
}

function FindControl(name) {
	return document.getElementById(name);
}

//<!-- Subscriber-Actions -->
function SetVariantImageUrl(subscriber, vm, dimension)
{
    if (subscriber == null ||  vm.selected.variant == null) return;
	 	
    subscriber.src = eval('vm.selected.variant.Images.' + dimension);

    if (vm.selected.variant.Name != null)
    {
        subscriber.alt = vm.selected.variant.Name;    
    }
}


//First attempt to solve problem with controller images
function SetVariantImageUrlOnController(subscriber, vm, imageDimension)
{
    if (subscriber == null) 
    {
        return;
    }
    
    var subscriberControlsDimension = subscriber.parentNode.attributes['ControlsDimension'].value;
    if (vm.selected.lastDimensionSet == '' || vm.selected.lastDimensionSet == subscriberControlsDimension) 
	{
	    return;
	}
	
    var selectedDimensions = vm.selected.variantDimensions;
    var subscriberDimensionValue = subscriber.parentNode.attributes['DimensionValue'].value;
    
    //Make a copy
    var selectedDimensionsString = JSON.stringify(selectedDimensions);
    var controllersDimensionsJSON = JSON.parse(selectedDimensionsString);
    
    //change the ccopy to a combination of the currently selected dimension WITH the controllers dimension value
    controllersDimensionsJSON[subscriberControlsDimension] = subscriberDimensionValue;
    
    var dimensionString = JSON.stringify(controllersDimensionsJSON);
    
    //go through all variants
    for(cvariantId in vm.productInfo.Variants) 
    {
	    var cvariant = vm.productInfo.Variants[cvariantId];
		
		//compare the current variants dimension with the copy dimension	
		if (JSON.stringify(cvariant.VariantDimensions) == dimensionString) 
		{
		    //if they are equal, set the image
            subscriber.src = eval('cvariant.Images.' + imageDimension);

            if (cvariant.Name != null)
            {
                subscriber.alt = cvariant.Name;    
            }
            
            break;
	    }
    }
}

function SetVariantControllerIcon(subscriber, vm, dimension){ SetVariantImageUrlOnController(subscriber, vm, dimension); }
function SetVariantImageUrlIcon(subscriber, vm, dimension){ SetVariantImageUrl(subscriber, vm, dimension); }
function SetVariantImageUrlNormal(subscriber, vm, dimension){ SetVariantImageUrl(subscriber, vm, dimension); }
function SetVariantImageUrlDetail(subscriber, vm, dimension){ SetVariantImageUrl(subscriber, vm, dimension); }
function SetVariantImageUrlLarge(subscriber, vm, dimension){ SetVariantImageUrl(subscriber, vm, dimension); }
function SetVariantImageUrlProductAdSmall(subscriber, vm, dimension){ SetVariantImageUrl(subscriber, vm, dimension); }

function SetVariantLabel(subscriber, vm, urlTemplate)
{
    if (subscriber == null) return;
    
    if (vm.selected.variant == null || !vm.selected.variant.HasImageLarge)
    {
        subscriber.style.visibility = "hidden";
        return;
    }
    
    subscriber.style.visibility = "visible";
    
    urlNew = urlTemplate.replace("tag_productid", vm.productInfo.ProductId).replace("tag_variantid", vm.selected.variant.VariantId).replace("tag_sq", vm.selected.productQuantity);

    subscriber.href = urlNew;
}

function SetVariantDetailNavigateUrl(subscriber, vm, urlTemplate)
{
    if (subscriber == null) return;
    
    if (vm.selected.variant == null )
    {
        subscriber.style.visibility = "hidden";
        return;
    }
    
    subscriber.style.visibility = "visible";
    
    urlNew = urlTemplate.replace("tag_productid", vm.productInfo.ProductId).replace("tag_variantid", vm.selected.variant.VariantId).replace("tag_sq", vm.selected.productQuantity);
    
    subscriber.href = urlNew;
}

function SetVariantDetailImageNavigateUrl(subscriber, vm, urlTemplate)
{
    if (subscriber == null) return;
    
    if (vm.selected.variant == null || !vm.selected.variant.HasImageLarge)
    {
        subscriber.style.visibility = "hidden";
        return;
    }
    
    subscriber.style.visibility = "visible";
    
    urlNew = urlTemplate.replace("tag_productid", vm.productInfo.ProductId).replace("tag_variantid", vm.selected.variant.VariantId).replace("tag_sq", vm.selected.productQuantity);
    
    subscriber.href = urlNew;
}

function SetVariantPrice(subscriber, vm)
{
    if (subscriber == null) return;
    
    if (vm.selected.variant == null )
    {
        subscriber.style.visibility = "hidden";
        return;
    }
    
    subscriber.style.visibility = "visible";
    subscriber.innerHTML = vm.selected.variant.Price.OriginalPrice;
}

function SetVariantDiscountSpan(subscriber, vm)
{
    if (subscriber == null) return;
    
    if (vm.selected.variant == null || !vm.selected.variant.Price.HasDiscount)
    {
        subscriber.style.display = "none";
        return;
    }
    
    subscriber.style.display = "inline";
}

function SetVariantDiscountPrice(subscriber, vm)
{
    if (subscriber == null) return;
    
    if (vm.selected.variant == null || !vm.selected.variant.Price.HasDiscount /*|| vm.selected.variant.Price.PriceDescription == null || vm.selected.variant.Price.PriceDescription == ""*/)
    {
        subscriber.style.visibility = "hidden";
        return;
    }
    
    subscriber.style.visibility = "visible";
    subscriber.innerHTML = vm.selected.variant.Price.CurrentPrice;
}

function SetVariantDiscountLabel(subscriber, vm)
{
    if (subscriber == null) return;
    
    if (vm.selected.variant == null || !vm.selected.variant.Price.HasDiscount /*|| vm.selected.variant.Price.PriceDescription == null || vm.selected.variant.Price.PriceDescription == ""*/)
    {
        subscriber.style.visibility = "hidden";
        return;
    }
    else {}
    
    subscriber.style.visibility = "visible";
    
    subscriber.innerHTML = vm.selected.variant.Price.PriceDescription;
}

function SetVariantStockMessageLabel(subscriber, vm, unavailableMessage)
{
    if (subscriber == null) return;
    
    if (vm.selected.variant == null)
    {
        subscriber.innerHTML = unavailableMessage;
    }
    else
    {
        subscriber.innerHTML = vm.selected.variant.Stock.StockMessage;
    }
}

function SetOrderSetVariantStockMessageLabel(subscriber, vm, unavailableMessage)
{
    if (subscriber == null) return;
    
    if (vm.selected.variant == null)
    {
        subscriber.innerHTML = unavailableMessage;
    }
    else
    {
        subscriber.innerHTML = vm.selected.variant.Stock.OrderSetItemStockMessage;
    }
}

function SetVariantStockMessageShortLabel(subscriber, vm, unavailableMessage)
{
    if (subscriber == null) return;
    
    if (vm.selected.variant == null)
    {
        subscriber.innerHTML = unavailableMessage;
    }
    else
    {
        subscriber.innerHTML = vm.selected.variant.Stock.StockMessageShort;
    }
}

function SetVariantOutOfStockLabel(subscriber, vm)
{
    if (subscriber == null) return;
    
    if (vm.selected.variant != null && vm.selected.variant.Stock.IsOutOfStock && vm.selected.variant.Stock.ShowStockMessage)
    {
        subscriber.style.visibility = "visible";
        subscriber.innerHTML = vm.selected.variant.Stock.OutOfStockMessageShort;
    }
    else
    {
        subscriber.style.visibility = "hidden";
    }
}

function SetQuantityDropDownList(subscriber, vm, maxValue) 
{
    if (subscriber == null) return;
     
    if (vm.selected.variant == null)
    {
        subscriber.disabled = true;
        return;
    }
    	
    var selectedIndex = subscriber.selectedIndex;
    subscriber.options.length = 0;
    
    var max = (vm.selected.variant.Stock.CurrentStock > maxValue) ? maxValue : vm.selected.variant.Stock.CurrentStock;
    var quantities = vm.productInfo.QuantityList.split(',');
    
    for(i = 0; i < quantities.length && quantities[i] <= max; i++)
    {
        subscriber.options[subscriber.options.length] = new Option(quantities[i],quantities[i]);
    }

    var maxIndex = subscriber.options.length - 1;
	var index = (selectedIndex > maxIndex) ? maxIndex : selectedIndex;
	if (index < 0) index = 0;

	vm.SetSelectedQuantity(subscriber.selectedIndex);
	subscriber.selectedIndex = index;
	
	if (vm.selected.variant.Stock.IsOutOfStock)
	{
	    subscriber.disabled = true;
	}
	else
	{
	    subscriber.disabled = false;
	}
}

function SetOrderButton(subscriber, vm) 
{
    if (subscriber == null) return;
    
    subscriber.style.display = (vm.selected.variant == null || vm.selected.variant.Stock.IsOutOfStock) ? "none" : "block";    
}

function SetOrderLabel(subscriber, vm)
{
	if (subscriber == null)
		return;
	
	subscriber.style.visibility = "hidden";
}

function SetAddToWishListButton(subscriber, vm) 
{
    if (subscriber == null) return;
    
    subscriber.style.visibility = (vm.selected.variant == null || ((vm.selected.variant.Stock.IsLimited || vm.selected.variant.Stock.IsLimitedSpecial) && vm.selected.variant.Stock.IsOutOfStock)) ? "hidden" : "visible";    
}

function SetAddedToWishListLabel(subscriber, vm)
{
	if (subscriber == null)
		return;
	
	subscriber.style.visibility = "hidden";
}

function SetHiddenInputVariantId(subscriber, vm)
{
    if (subscriber == null || vm.selected.variant == null) return;
    subscriber.value = vm.selected.variant.VariantId;
}

function SetHiddenInputVariantName(subscriber, vm)
{
    if (subscriber == null || vm.selected.variant == null) return;
    subscriber.value = vm.selected.variant.Name;    
}

function SetNotifyMeDisplay(subscriber, vm)
{
    if (subscriber == null) return;
    
    if (vm.selected.variant != null && vm.selected.variant.Stock.IsOutOfStock && vm.selected.variant.Stock.IsUnlimited)
    {
        subscriber.style.display = "block";
    }
    else
    {
        subscriber.style.display = "none";
    }
}

function SetVariantControllerLink(subscriber, vm)
{
    if ( subscriber == null) return;
    
    var selectedVariant = vm.selected.variant;
    var selectedDimensions = vm.selected.variantDimensions;
	
	//get the subscribers custom attributes
    var subscriberIsVisualController = eval(subscriber.attributes['IsVisualController'].value);
    var subscriberControlsDimension = subscriber.attributes['ControlsDimension'].value;
    var subscriberDimensionValue = subscriber.attributes['DimensionValue'].value;
  
    if (selectedDimensions[subscriberControlsDimension] == subscriberDimensionValue )
	{
    	if (selectedVariant == null)
    	{
    	    subscriber.className = subscriberIsVisualController == true ? "selectedNostock" : "nostock selected";
    	}
    	else
    	{
    	    subscriber.className = "selected";
    	}
	}
	else //the subscriber is not a controller for the currently selected dimensions
	{
		if ( SubscribersDimensionIsInvalid(vm, subscriberControlsDimension, subscriberDimensionValue, selectedDimensions ) ) 
		{
    		subscriber.className = "nostock";
		}
		else
		{
			subscriber.className = "";
		}
    }
}

function SubscribersDimensionIsInvalid(vm, dimension, value, selectedDimensions)
{
    var isInvalid = true;

    //make a copy of the JSON array
    var selectedDimensionsString = JSON.stringify(selectedDimensions);
    var controllersDimensionsJSON = JSON.parse(selectedDimensionsString);
    
    //change the dimension to a combination of the currently selected dimension WITH the controllers dimension value
    controllersDimensionsJSON[dimension] = value;
    
    var dimensionString = JSON.stringify(controllersDimensionsJSON);
    
    //go through all variants
    for(cvariantId in vm.productInfo.Variants) 
    {
	    var cvariant = vm.productInfo.Variants[cvariantId];
		
		//compare the current variants dimension with the controllers dimension	
		if (JSON.stringify(cvariant.VariantDimensions) == dimensionString ) 
		{
		    //if they are equal, return whether the variant is out of stock
		    isInvalid = false;
		    break;
	    }
	}
	
	//there is no variant so out of stock
	return isInvalid;
}

function SetVariantDimensionsLabel(subscriber, vm, invalidSelectionMessage)
{
	if ( subscriber == null ) return;
	
	var selectedVariantString = ""; 
	
	if ( vm.selected.variant == null )
	{
        selectedVariantString = invalidSelectionMessage;
	}
	else
	{
	    var selectedDimensions = "";
	    var dimensions = vm.selected.variantDimensions;
	    
	    for ( var dimension in dimensions)
	    {
		    if ( dimensions[dimension] != "" )
		    {
			    selectedDimensions += dimensions[dimension] + ", ";
		    }
	    }
	    
	    selectedVariantString = selectedDimensions.substring(0, selectedDimensions.length-2);
	}

	var newNode = document.createTextNode(selectedVariantString);
	
    if (subscriber.firstChild == null)
	{
	    subscriber.appendChild(newNode);
	}
	else
	{
	    subscriber.replaceChild(newNode, subscriber.firstChild);
	}
    
    //this only worked in IE but failed in FF	
    //subscriber.innerText = selectedDimensions.substring(0, selectedDimensions.length-2);
}

// Order set functions.
//**********************************************************

/*
	The object orderSetSelectedVariants contains the selected price and quantity information for each selected variant.
	This array is used to calculate the total price of all selected items (each time another variant is selected or the 
	quantity gets changed).
*/
var orderSetSelectedVariants = {};

/*
	The object 'OrderSetSelectedVariant' is the object used for keeping track of which variant is selected.
*/
function OrderSetSelectedVariant(variantId, price, quantity)
{
	this.variantId = variantId;
	this.price = price;
	this.quantity = quantity;
}

function SetOrderSetVariantQuantityDropDownList(subscriber, vm, maxValue) 
{
    if (subscriber == null) return;
     
    if (vm.selected.variant == null)
    {
        subscriber.disabled = true;
        return;
    }
    
    var selectedIndex = subscriber.selectedIndex;
    subscriber.options.length = 0;
    
    var max = (vm.selected.variant.Stock.CurrentStock > maxValue) ? maxValue : vm.selected.variant.Stock.CurrentStock;
    var quantities = vm.productInfo.OrderSetQuantityList.split(',');
    
    for(i = 0; i < quantities.length && quantities[i] <= max; i++)
    {
        subscriber.options[subscriber.options.length] = new Option(quantities[i],quantities[i]);
    }

    var maxIndex = subscriber.options.length - 1;
	var index = (selectedIndex > maxIndex) ? maxIndex : selectedIndex;
	if (index < 0) index = 0;
	
	vm.SetSelectedQuantity(index);
	subscriber.selectedIndex = index;
	
	if (vm.selected.variant.Stock.IsOutOfStock)
	{
	    vm.SetSelectedQuantity(0);
	    subscriber.disabled = true;
	}
	else
	{
	    subscriber.disabled = false;
	}
}

/*
	Event handler for setting the the total price on a label. ProductId is used
	as the key in the hashtable for setting the current variant information
*/
function SetOrderSetPriceLabel(subscriber, vm)
{
	if (subscriber == null) return;

	var totalPrice = 0;
	var productId = vm.productInfo.ProductId;
	var variantId = vm.selected.variant.VariantId;
	var price = vm.selected.variant.Price.HasDiscount ? vm.selected.variant.Price.CurrentPrice : vm.selected.variant.Price.OriginalPrice;
	var quantity = vm.selected.productQuantity;
	var selectedVariant = null;
		
	if (!(productId in orderSetSelectedVariants))
	{
		selectedVariant = new OrderSetSelectedVariant(variantId, price, quantity);
		orderSetSelectedVariants[productId] = selectedVariant;
	}
	else
	{
		selectedVariant = orderSetSelectedVariants[productId]; 
		selectedVariant.variantId = variantId;
		selectedVariant.price = price;
		selectedVariant.quantity = quantity;	
	}		
	
	for (key in orderSetSelectedVariants)
	{
		var selectedVariant = orderSetSelectedVariants[key];
		totalPrice += (selectedVariant["price"] * selectedVariant["quantity"]); 
	}
	
	subscriber.innerHTML = totalPrice.toFixed(2);
}

//function DisplayLoadingSpinners() 
//{
//	for (key in orderSetSelectedVariants)
//	{
//		var orderedQuantity = orderSetSelectedVariants[key]["quantity"];
//		
//		if (orderedQuantity > 0)
//		{
//			var elementId = 'loading_spinner_' + key;
//			var loadingSpinnerDiv = document.getElementById(elementId);
//			loadingSpinnerDiv.style.visibility = 'visible';
//		}
//	}
//}

function onUpdating(parentDiv) 
{
	var updateProgressDiv = document.getElementById('updateProgressDiv'); 
	var updateProgressBackgroundElement = document.getElementById('updateProgressBackgroundElement'); 

	if (updateProgressDiv != null)
	{
		updateProgressDiv.style.display = 'block';
		updateProgressDiv.style.visibility = 'visible';
	}
		
	if (updateProgressBackgroundElement != null)
	{
		updateProgressDiv.style.display = 'block';
		updateProgressBackgroundElement.style.visibility = 'visible';
	}
}

function SetOrderSetButton(subscriber, vm) 
{
    if (subscriber == null) return;
    
    var orderedQuantity = 0;
    
    for (key in orderSetSelectedVariants)
	{
		orderedQuantity += orderSetSelectedVariants[key]["quantity"];
	}
    
    subscriber.disabled = orderedQuantity > 0 ? false : true;    
}

function SetHiddenOrderSetVariantId(subscriber, vm)
{
    if (subscriber == null || vm.selected.variant == null) return;
    subscriber.value = vm.selected.variant.VariantId;
}
//**********************************************************


//extra scripts
function changeImgQuantity(list, url, productLinkID)
{
	var productLink = document.getElementById(productLinkID);
	var link = url;
    
	
	if (productLink != null && productLink.href != null && list.value != '0')
	{	    
		link += (url.indexOf('?') > -1 ? '&' : '?') + 'SelQty=' + list.value;
	    productLink.href = link;
	}
}