﻿//	2007-07-24/StephanD: added currency id
var currencyID = 'EUR';

Type.registerNamespace('Shop1');

// Summary:
//	Object (controller) to communicate with webservice and gui.
Shop1.AjaxConfigurator = function(element, instanceID) {
	// The country ID for database selection
    this._countryID = '';
    // The instrument ID itself
    this._variantID = '';
    // Contains instrument structure. Gets synchronized from server 
    // with curretn values.
    this._data = null;
    // Container gui element for the configurator gui. 
    this._element = element;
    // The Unique ID for this instance.
    this.InstanceID = instanceID;
    // Track remote calls to update/block gui 
    this._wait = false;
    // Add this instance to the pool. This is needed because callbacks
    // cannot hit instance members. Therefore there are special global
    // callback handlers (starts with _onGlobal*) outside of this class
    // definition.
    PoolService.add_instance(this);
}
// Summary:
//	Method definitions
Shop1.AjaxConfigurator.prototype = {
	
	initialize : function() {
	},

	dispose : function() {
	},
	
	// Summary:
	//	Show popup with feature value list to select a new feature value.
	ShowPopup : function(e, event, featureID) {
		// if we are still do a remote call, ignore this and return
		if (this._inProgress()) 
			return;
		// get feature to populate values
		var feature = this._findFeature(featureID);
		var s = "";
		s += "<table class='FeatureValuePopup'><col id='DropDownMenuCol1'/><col id='DropDownMenuCol2'/>";
		for (var i = 0; i < feature.FeatureValues.length; i++)
		{
			if(feature.FeatureValues[i].IsValid) {
				s += "<tr class='FeatureValueRow' onclick=\"PoolService.get_instance('{instanceID}').setFeature({featureID}, {featureValue});\">";
				s += "<td onclick=\"PoolService.get_instance('{instanceID}').setFeature({featureID}, {featureValue});\">{orderNumberPart}</td><td>" + feature.FeatureValues[i].Description + "</td>";
				s = s.replace(/{instanceID}/gi, this.InstanceID);
				s = s.replace(/{featureID}/gi, featureID);
				s = s.replace(/{featureValue}/gi, feature.FeatureValues[i].Value);
				s = s.replace(/{orderNumberPart}/gi, feature.FeatureValues[i].OrderNumberPart);
				s += "</tr>";
			}
		}
		s += "</table>";
		// show drop down
		return dropdownmenu(e, event, s, e.clientWidth);
	},
	// Summary:
	//	Create all controls. This is called only once on initialize callback.
	_createControls : function(element) {

		element.innerHTML = "";
		var d = document.createElement("div");
		element.appendChild(d);
		
		var s = "";
		// header
		s += "<table>";
		s += "<col class='col1'/><col class='col2'/><col class='col3'/><col class='col4'/>";
		s += "<tr class='OrderNumberRow'>";
		s += "<td>" + AjaxResources.Configurator.OrderCodeColumnCaption + "</td>";
		s += "<td colspan='3'><div id='divOrderNumber' class='divOrderNumber'>{orderNumber}</div></td>";
		s += "</tr>";
		s += "<tr>";
		s += "<td>" + AjaxResources.Configurator.QuantityColumnCaption + "</td>";

		s += "<td><input class='inputClass' id='inputQuantity' type='text' value='{quantity}'" +
				" onkeyup='PoolService.get_instance(\"{instanceID}\")._checkQuantity();' />";
		s += "&nbsp;<input type='button' class='subMit' id='btnQuantityUpdate' value='" + AjaxResources.Configurator.AcceptButtonText + "' style='visibility:hidden;' onclick=\"PoolService.get_instance('{instanceID}').setQuantity();\"/></td>";
		s += "<td>" + AjaxResources.Configurator.BasePriceColumnCaption + "</td>";
		s += "<td><div id='divBaseUnitPrice'>{baseUnitPrice}</div></td>";
		s += "</tr>";
		
		s = s.replace(/{orderNumber}/gi, this._data.OrderNumber);
		s = s.replace(/{quantity}/gi, this._data.Quantity);
		s = s.replace(/{baseUnitPrice}/gi, formatPrice(this._data.BaseUnitPrice));
		s = s.replace(/{InstanceID}/gi, this.InstanceID);
		// features
		for (var i = 0; i < this._data.Features.length; i++)
		{
			var f = this._data.Features[i];

			var sr = "";
			sr += "<tr class='FullFeatureRow'>";
			sr += "<td>{description}</td>";
			sr = sr.replace(/{description}/gi, f.Description);
			
			if (f.IsTable) 
			{
				sr += this._createTableFeatureControls(f);
			}
			else
			{
				sr += this._createRangeFeatureControls(f);
			}
			sr += "<td><div id='divPrice_{featureID}'>{price}</td>";
			sr = sr.replace(/{featureID}/gi, f.ID);
			sr = sr.replace(/{price}/gi, formatPrice(f.Price));
			sr += "</tr>";
			
			s += sr;
		}
		
		// footer
		s += "<tr class='TotalAmountRow'>";
		s += "<td colspan='3'>" + AjaxResources.Configurator.TotalAmountColumnCaption + "</td>";
		s += "<td><div id='divTotalAmount' class='TotalAmountCell'>{totalAmount}</div></td>";
		s = s.replace(/{totalAmount}/gi, formatPrice(this._data.TotalAmount));
		s += "</tr>";
		
		s += "</table>";
		s += "<div id='progress'></div>";

		
		d.innerHTML = s;
		var basketTarget = $get('BasketInfo');
		
	},
	
	_createTableFeatureControls : function(feature) {
		var orderNumberPart = "";
		var featureValueDescription = "";
		var featureValue = this._findFeatureValue(feature, feature.CurrentValue);
		if (featureValue != null) 
		{
			orderNumberPart = featureValue.OrderNumberPart;
			featureValueDescription = featureValue.Description;
		}
		
		var id = this.InstanceID + "_feature_" + feature.ID;
		var s = "";
		
		s += "<td class='FeatureSelector' colspan='2' onclick=\"PoolService.get_instance('{instanceID}').ShowPopup($get('" + id + "', this), event, {featureID});\">";
		s += "<div>";
		s += "<table id='" + id + "' class='FeatureValueTable'>";
		s += "<col class='OrderNumberPartColumn'/><col class='FeatureValueDescriptionColumn'/><col class='DropDownColumn'/>";
		s += "<tr>";
		s += "<td><div class='FeatureValueOrderNumberPart' id='divFeatureValueOrderNumberPart_{featureID}'>{featureValueOrderNumberPart}</div></td>";
		s += "<td><div class='FeatureValueDescription' id='divFeatureValueDescription_{featureID}'>{featureValueDescription}</div></td>";
		s += "<td><div class='FeatureValueDropDownSelector'><img src='shopservices/images/dropdown.gif' /></div></td>";
		s += "</tr>";
		s += "</table>";
		s += "</div>";
		s += "</td>";
		s = s.replace(/{InstanceID}/gi, this.InstanceID);
		s = s.replace(/{FeatureID}/gi, feature.ID);
		s = s.replace(/{featureValueOrderNumberPart}/gi, orderNumberPart);
		s = s.replace(/{featureValueDescription}/gi, featureValueDescription);
	
		return s;
	},

	_createRangeFeatureControls : function(feature) {

		var rangeLimit = "(" + feature.MinimumValue + " bis " + feature.MaximumValue + ")";
		var s = "";

		s += "<td colspan='2' class='RangeLimitSelector'>";
		s += "<input class='inputClass' id='input_{featureID}' type='text' value='{quantity}'" +
				" onkeyup='PoolService.get_instance(\"{instanceID}\")._checkRange({featureID});' />";
		s += "&nbsp;<input class='subMit' type='button' id='btnRangeUpdate_{FeatureID}' value='" + AjaxResources.Configurator.AcceptButtonText + "' style='visibility:hidden;' onclick=\"PoolService.get_instance('{instanceID}').setRange({featureID});\"/>";
		s += "&nbsp;<span class='rangeLimit' id='rangeLimit_{featureID}'>{rangeLimit}</span>";
		s += "</td>";
		s = s.replace(/{FeatureID}/gi, feature.ID);
		s = s.replace(/{Quantity}/gi, feature.CurrentValue);
		s = s.replace(/{RangeLimit}/gi, rangeLimit);
		s = s.replace(/{InstanceID}/gi, this.InstanceID);

		return s;
	},
	// Summary:
	//	Set progress tracker and update gui information
	_startProgress : function() {
		this._wait = true;
		this._updateProgress();
	},
	// Summary:
	//	Set progress tracker and update gui information
	_stopProgress : function() {
		this._wait = false;
		this._updateProgress();
	},
	// Summary:
	//	Retruns true if there is still a remote call running
	_inProgress : function() {
		return this._wait;
	},
	// Summary:
	//	Set progress tracker and update gui information
	_updateProgress : function() {
		var p = $get('progress', this._element);
		if (p != null)
			p.innerHTML = this._inProgress() ? AjaxResources.Configurator.PleaseWaitInfo : '';
	},
	// Summary:
	//	Callback function. Only called one on intialize to create gui
    _onInitializeComplete : function (summary) {
		this._data = summary;
		this._createControls(this._element);
		this._stopProgress();
    },
    // Summary:
	//	Callback function. This is called on every server round trib to update 
	//	the gui.
    _onResultComplete : function(summary) {
		this._data.Quantity = summary.Quantity;
		this._data.OrderNumber = summary.OrderNumber;
		this._data.BaseUnitPrice = summary.BaseUnitPrice;
		var allValid = true;
		// SyncFeatures is the same as Features but with no Description set to save band width
		for (var i=0; i < summary.Features.length; i++)
		{
			var s = summary.Features[i];
			var f = this._findFeature(s.ID);

			f.CurrentValue = s.CurrentValue;
			f.IsSet = s.IsSet;
			f.Price = s.Price;
			
			//TODO: implement this
//			if (!f.IsSet)
//				allValid = false;
			
			if(f.IsTable)
			{
				for (var j = 0; j < s.FeatureValues.length; j++)
				{
					sfv = s.FeatureValues[j];
					var fv = this._findFeatureValue(f, sfv.Value);
					fv.IsValid = sfv.IsValid;
					if (fv.Value == f.CurrentValue && !fv.IsValid)
						allValid = false;
				}
			}
			else
			{
				f.MinimumValue = s.MinimumValue;
				f.MaximumValue = s.MaximumValue;
				if (f.CurrentValue < f.MinimumValue || f.CurrentValue > f.MaximumValue)
					allValid = false;
			}
			
			this._updateFeature(f);
		}
		if (allValid)
			this._data.TotalAmount = summary.TotalAmount;
		else
			this._data.TotalAmount = 0;
		this._updateHeader();
		this._stopProgress();
    },
	// Summary: 
	//	Create instance
	load : function(countryID, variantID) {
		this._countryID = countryID;
		this._variantID = variantID;
		this._startProgress();
		PageMethods.CreateInstance(this.InstanceID, this._countryID, this._variantID, _globalOnInitializeComplete);
    },
	   
	// Summary:
	//	load from cart
    loadCart : function(cartID) {
    },
	    
    setQuantity : function() {
		this._startProgress();
		this._updateQuantity(false);
		var value = $get('inputQuantity', this._element).value;
		PageMethods.SetQuantity(this.InstanceID, value, _globalOnResultComplete);
    },
 
    setFeature : function(id, value) {
		this._startProgress();
		PageMethods.SetFeature(this.InstanceID, id, value, _globalOnResultComplete);
    },

    setRange : function(id) {
		this._startProgress();
		this._updateRange(id, false);
		var value = $get('input_' + id, this._element).value;
		PageMethods.SetFeature(this.InstanceID, id, value, _globalOnResultComplete);
    },

	_checkRange : function(id) {
		var unsaveValue = $get('input_' + id, this._element).value;
		// check range for decimal(12,3);
		var value = unsaveValue.toString().match(/\d{1,12}\.\d{1,3}/);
		if (value == null) {
			// no decimal, check for int
			value = unsaveValue.toString().match(/\d{1,12}/);
		}
		if (value != null) {
			// is valid value, check if changed
			var feature = this._findFeature(id);
			if (feature.CurrentValue != value)
			{
				this._updateRange(id, true);
			}
			else
			{
				this._updateRange(id, false);
			}
		}
		else
		{
			this._updateRange(id, false);
		}
	},
	
	_updateRange : function(id, valid) {
		var button = $get('btnRangeUpdate_' + id, this._element);
		button.style.visibility = valid ? 'visible' : 'hidden';
		//var input = $get('input_' + feature.ID, this._element);
	},

	_checkQuantity : function() {
		var e = $get('inputQuantity', this._element);
		var unsaveValue = e.value;
		// check range for decimal(12,3);
		var value = unsaveValue.toString().match(/\d{1,12}\.\d{1,3}/);
		if (value == null) {
			// no decimal, check for int
			value = unsaveValue.toString().match(/\d{1,12}/);
		}
		if (value != null) {
			if (value > 100)
			{
				e.value = value = 100;
			}
			if (this._data.Quantity != value)
			{
				this._updateQuantity(true);
			}
			else
			{
				this._updateQuantity(false);
			}
		}
		else
		{
			this._updateQuantity(false);
		}
	},
	
	_updateQuantity : function(valid) {
		var button = $get('btnQuantityUpdate', this._element);
		button.style.visibility = valid ? 'visible' : 'hidden';
		//var input = $get('input_' + feature.ID, this._element);
	},
	
    _updateHeader : function() {
		var e = $get('inputQuantity', this._element);
		e.value = this._data.Quantity;
		
		var e = $get('divTotalAmount', this._element);
		e.innerHTML = formatPrice(this._data.TotalAmount);

		var e = $get('divOrderNumber', this._element);
		e.innerHTML = this._data.OrderNumber;
		
	},
	
	_updateFeature : function(feature) {
		if	(feature.IsTable)
		{
			var fv = this._findFeatureValue(feature, feature.CurrentValue);

			var ft = $get("divFeatureValueDescription_" + feature.ID);
			ft.innerHTML = fv.Description;
			
			if (fv.IsValid)
				ft.style.color = "black";
			else
				ft.style.color = "red";
	
			if (fv.OrderNumberPart != 'undefined') {
				var onp = 	$get("divFeatureValueOrderNumberPart_" + feature.ID);
				onp.innerHTML = fv.OrderNumberPart;
			}

		}
		else
		{
			var fr = $get("input_" + feature.ID);
			var frr = $get("rangeLimit_" + feature.ID);
			fr.value = feature.CurrentValue;
			frr.innerHTML = "(" + feature.MinimumValue + " ... " + feature.MaximumValue + ")";
		}

		var p = $get("divPrice_" + feature.ID);
		p.innerHTML = formatPrice(feature.Price);
	},
	   
	_updateOrderNumber : function (orderNumber){
	},

	_updateBaseUnitPrice : function(price) {
	},
	   
	_updateTotalPrice : function(price) {
	},
	   
	_updateFeaturePrice : function (id, price) {
	},
	   
	    
	_findFeature : function(id) {
		for (var i = 0; i < this._data.Features.length; i++)
		{
		   var feature = this._data.Features[i];
		   if (feature.ID == id)
			   return feature;
		}
		return null;
    },
	    
    _findFeatureValue : function (feature, value) {
		for (var i = 0; i < feature.FeatureValues.length; i++)
		{
			var featureValue = feature.FeatureValues[i];
			if (featureValue.Value == value)
				return featureValue;
		}
		return null;
    },
    
    dispose : function() {
    
		PageMethods.DestroyInstance(this._instanceID);
		PoolService.remove_instance(this);
		this._disposed = true;
    },
    
    _checkDisposed : function() {
		if(this._disposed)
			throw new Shop1.ObjectDisposedException('This object is disposed');
    }
}
// global callback handlers
function _globalOnInitializeComplete(summary) {
	var instance = PoolService.get_instance(summary.InstanceID);
	instance._onInitializeComplete(summary);
}

function _globalOnResultComplete(summary) {
	var instance = PoolService.get_instance(summary.InstanceID);
	instance._onResultComplete(summary);
}

PoolService = function() {
	this._instances = new Array(100);
}

PoolService.prototype = {
	add_instance : function(instance) {
		for (var i = 0; i < 10; i++)
		{
			if(this._instances[i] == 'undefined' || this._instances[i] == null)
			{
				this._instances[i] = instance;
				return;
			}
		}
	},
	
	remove_instance : function(instance) {
		this._instances[this.get_index(instanceID)] = null;
	},
	
	get_instance : function(instanceID) {
		return this._instances[this.get_index(instanceID)];
	},
	
	get_index : function(instanceID) {
		for (var i = 0; i < 10; i++)
		{
			var instance = this._instances[i];
			if(instance != null && instance.InstanceID == instanceID)
				return i;
		}
		return -1;
	}
	
}

// Summary:
//	Use this to format the price or replace invalid data
//	2007-07-24/StephanD: added currency id
function formatPrice(price) {
	if(price == 'undefined' || price == null || price == 0)
		return "-";
	else
		return price.toFixed(2).toString().replace('.', ',') + " " + currencyID;
}

// Summary:
//	Use this to format the price or replace invalid data
function formatPercent(rate) {
	if(rate == 'undefined' || rate == null)
		return 0;
	else {
		rate *= 100;
		return rate.toFixed(1).toString().replace('.', ',') + " %";
	}
}

var PoolService = new PoolService();

//Shop1.ObjectDisposedException = function(message) {
//	this.message = message;
//}

//Shop1.AjaxConfigurator.registerClass('Shop1.AjaxConfigurator', null, Sys.IDisposable);

// notify script manager for script end 
if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();

