var Attributes = {};
Attributes.attributeManager = function(config) {
	var currentProductData = null;
	var currentProductPrice = null;
	var activeVariationIndex = null;
	return {
		webshopitem: null,
		variations: null,
		updatePrice: true,
		attributesConfig: null,
		webshopSettings: null,
		localSettings: null,
		usePricesWithVat: false,
		hierarchy: null,
		hideInvalidOptions: null,
		disableInvalidOptions: null,
		displayStockMinusReserved: null,
		outOfStockShowCanBePurchased: null,
		groupingOption: false,
		groupAttributevalueData: null,
		groupIdPrefix: '',
		attributes: {},
		variationAttributesTable: [],
		variationAttributehashTable: [],
		attributeIdToKey: function(attributeId) {
			return 'attribute_key_' + attributeId.toString();
		},
		keyToAttributeId: function(attributeIdKey) {
			return parseInt(attributeIdKey.replace('attribute_key_', ''));
		},
		getVariationHashPattern: function(attributeId) {
			var hashPattern = '';
			var hashPatternArray = [];
			// Forming hash pattern
			for (var currentAttributeIdKey in this.attributes) {
				if ('VARIABLE' == this.attributes[currentAttributeIdKey].type) {
					if (attributeId == this.keyToAttributeId(currentAttributeIdKey)) {
						hashPatternArray.push('attribute_match');
					} else {
						hashPatternArray.push(this.attributes[currentAttributeIdKey].getSelectedOption().value);
					}
				}
			}
			hashPattern = hashPatternArray.join('-');

			return hashPattern;
		},
		getVariationHash: function(hashPattern, optionValue) {
			return hashPattern.replace('attribute_match', optionValue);
		},
		getPossibleVariableAttributeOptions: function(attributeId) {
			var hashPatternArray = [];
			// Forming hash pattern of selected options from first to attribute being changed
			for (var currentAttributeIdKey in this.attributes) {
				if ('VARIABLE' == this.attributes[currentAttributeIdKey].type) {
					if (attributeId == this.keyToAttributeId(currentAttributeIdKey)) {
						break;
					}
					hashPatternArray.push(this.attributes[currentAttributeIdKey].getSelectedOption().value);
				}
			}
			var hashPattern = hashPatternArray.join('-');

			var possibleAttributeOptions = [];
			for(var hash in this.variationAttributehashTable) {
				var option = null;
				if ('' == hashPattern) {
					var option = this.attributes[this.attributeIdToKey(attributeId)].getOption(hash.split('-').shift());
				} else if (-1 != hash.indexOf(hashPattern)) {
					var option = this.attributes[this.attributeIdToKey(attributeId)].getOption(hash.replace(hashPattern + '-', '').split('-').shift());
				}

				if (option && !Common.inArray(option, possibleAttributeOptions)) {
					possibleAttributeOptions.push(option);
				}
			}

			return possibleAttributeOptions;
		},
		priceAddonSum: 0,
		weightAddonSum: 0,
		setConfigData: function(config) {
			this.webshopitem = config.webshopitem;
			this.variations = this.reorderVariationsOptionsBasedOnAttributes(config);
			this.updatePrice = ('undefined' != typeof(config.updatePrice)) ? config.updatePrice : true;
			this.attributesConfig = config.attributesConfig;
			this.webshopSettings = config.webshopSettings;
			this.localSettings = config.localSettings;
			this.usePricesWithVat = config.usePricesWithVat;
			this.hierarchy = config.hierarchy;
			this.hideInvalidOptions = config.hideInvalidOptions;
			this.disableInvalidOptions = config.disableInvalidOptions;
			this.displayPrices = config.displayPrices;
			this.displayStockMinusReserved = config.displayStockMinusReserved,
			this.outOfStockShowCanBePurchased = config.outOfStockShowCanBePurchased,
			this.groupAttributevalueData = ('undefined' != typeof(config.groupAttributevalueData)) ? config.groupAttributevalueData : null;
			this.groupIdPrefix = ('undefined' != typeof(config.groupIdPrefix)) ? config.groupIdPrefix : '';
			this.mainImage = config.mainImage;
		},
		reorderVariationsOptionsBasedOnAttributes: function(config) {
			if (0 >= config.variations.length) {
				return [];
			}

			var reorderedVariationsOptions = {};
			for (var i = 0; i < config.attributesConfig.length; i++) {
				if ('VARIABLE' != config.attributesConfig[i]['ProductsAttribute']['type']) {
					continue;
				}

				for (var j = 0; j < config.variations.length; j++) {
					if ('undefined' == typeof(reorderedVariationsOptions[j])) {
						reorderedVariationsOptions[j] = [];
					}

					for (var k = 0; k < config.variations[j]['ProductsAttributevalue'].length; k++) {
						if (config.attributesConfig[i]['id'] == config.variations[j]['ProductsAttributevalue'][k]['attribute_id']) {
							reorderedVariationsOptions[j].push(config.variations[j]['ProductsAttributevalue'][k]);
							config.variations[j]['ProductsAttributevalue'].splice(k, 1);
							break;
						}
					}
				}
			}

			for (var i = 0; i < config.variations.length; i++) {
				config.variations[i]['ProductsAttributevalue'] = reorderedVariationsOptions[i];
			}

			return config.variations;
		},
		getHash: function() {
			var str = document.location.hash;
			return str.substring(1, str.length); // Cut the '#'
		},
		getHistory: function() {
			if (!this.getHash().length) {
				return null;
			}

			var urlInfo = this.getHash().split('=');
			return (1 < urlInfo.length) ? decodeURIComponent(urlInfo[1]) : null;
		},
		setHistory: function() {
			var variationIndex = this.getActiveVariationIndex();
			if (null == variationIndex) {
				return;
			}

			document.location.hash = 'variation=' + encodeURIComponent(this.variations[variationIndex]['id']);
		},
		setProductPrice: function(newPrice) {
			currentProductPrice = newPrice;
		},
		getProductPrice: function(productData, getOriginalPrice) {
			var productDataOverriden = false;
			if ('undefined' == typeof(productData) || false === productData) {
				productData = this.getProductData();
			} else {
				productDataOverriden = true;
			}

			if ('undefined' == typeof(getOriginalPrice)) {
				getOriginalPrice = false;
			} else {
				productDataOverriden = true;
			}

			var priceToReturn = 0;
			var newProductPrice = 0;
			if (null == currentProductPrice || productDataOverriden) {
				if (null != productData) {
					var priceIndexToUse = '';
					if (!getOriginalPrice) {
						priceIndexToUse = this.usePricesWithVat ? 'price_with_tax' : 'price';
					} else {
						priceIndexToUse = this.usePricesWithVat ? 'original_price_with_tax' : 'original_price';
					}

					var newProductPrice = parseFloat(productData['Webshopitem'][priceIndexToUse]);
					for (var attributeIdKey in this.attributes) {
						var priceAddon = this.attributes[attributeIdKey].getSelectedOption().getPriceAddon(productData, getOriginalPrice);
						newProductPrice += parseFloat(priceAddon);
					}

					if (this.groupAttributevalueData) {
						if (!this.groupingOption) {
							this.groupingOption = new Attributes.AttributeOption(this.groupAttributevalueData, this);
						}
						newProductPrice += parseFloat(this.groupingOption.getPriceAddon(productData, getOriginalPrice));
					}
				}

				if (!productDataOverriden) {
					this.setProductPrice(newProductPrice);
				}

				priceToReturn = newProductPrice;
			} else {
				priceToReturn = currentProductPrice;
			}
			return priceToReturn;
		},
		calculatePriceAddon: function(price, priceType, productData) {
			if ('undefined' == typeof(productData)) {
				productData = this.getProductData();
			}
			var priceToReturn = 0;

			if (null != productData) {
				if ('AMOUNT' == priceType) {
					priceToReturn = (!this.usePricesWithVat)? price : (price * (1 + parseFloat(productData['Vat']['value'])));
				} else {
					var priceIndexToUse = this.usePricesWithVat ? 'price_with_tax' : 'price';
					var currentPrice = productData['Webshopitem'][priceIndexToUse];
					priceToReturn = (currentPrice * price) / 100;
				}
			}

			return priceToReturn;
		},
		getProductData: function() {
			if (null == currentProductData) {
				var newProductData = null;

				if ((null != this.variations) && (0 < this.variations.length)) {
					currentlyActiveVariationIndex = this.getActiveVariationIndex();

					if (null !== currentlyActiveVariationIndex) {
						newProductData = this.variations[currentlyActiveVariationIndex];
					}
				} else {
					newProductData = this.webshopitem;
				}

				this.setProductData(newProductData);
			}

			return currentProductData;
		},
		setProductData: function(dataToSet) {
			currentProductData = dataToSet;
		},
		getActiveVariationIndex: function() {
			if (null === activeVariationIndex) {
				if (null != this.variations && 0 < this.variations.length) {
					var hash = '';
					var hashPatternArray = [];
					// Forming hash pattern
					for (var currentAttributeIdKey in this.attributes) {
						if ('VARIABLE' == this.attributes[currentAttributeIdKey].type) {
							hashPatternArray.push(this.attributes[currentAttributeIdKey].getSelectedOption().value);
						}
					}
					hash = hashPatternArray.join('-');

					var newIndexToSet = ('undefined' != typeof(this.variationAttributehashTable[hash]))? this.variationAttributehashTable[hash] : null;

					this.setActiveVariationIndex(newIndexToSet);
				}
			}

			return activeVariationIndex;
		},
		setActiveVariationIndex: function(indexToSet) {
			activeVariationIndex = indexToSet;
		},
		init: function(config) {
			this.setConfigData(config);

			for (var i = 0; i < this.attributesConfig.length; i++) {
				var newAttribute = new Attributes.Attribute(this.attributesConfig[i], this);
				this.attributes[this.attributeIdToKey(newAttribute.id)] = newAttribute;
			}

			var historyVariationId = this.getHistory();
			var historyVariationIndex = null;
			for (var i = 0; i < this.variations.length; i++) {
				this.variationAttributesTable[i] = {};

				var attributeArray = [];
				for (var j = 0; j < this.variations[i]['ProductsAttributevalue'].length; j++) {
					var attributeId = this.variations[i]['ProductsAttributevalue'][j]['attribute_id'];
					var attributeOptionValue = this.variations[i]['ProductsAttributevalue'][j]['value'];

					this.variationAttributesTable[i][attributeId] = attributeOptionValue;
					attributeArray.push(attributeOptionValue);
				}
				var attributeHash = attributeArray.join('-');
				this.variationAttributehashTable[attributeHash] = i;

				if (historyVariationId && (historyVariationId == this.variations[i]['id'])) {
					historyVariationIndex = i;
				}
			}

			// Set variation from history as selected one
			if (null != historyVariationIndex) {
				for (var attributeIdKey in this.attributes) {
					if ('VARIABLE' != this.attributes[attributeIdKey].type) {
						continue;
					}

					this.attributes[attributeIdKey].setSelectedOption(this.variationAttributesTable[historyVariationIndex][this.keyToAttributeId(attributeIdKey)]);
				}
			}

			if (0 < this.attributesConfig.length) {
				this.onSelectionChange(this.attributesConfig[0]['id'], true);
			}
		},
		updateProductView: function(previousVariationId) {
			var submitFormButton = $('submit_form_button');
			var hiddenFieldVariationId = $('hidden_field_variation_id');
			var productItemId = $('product_item_id');
			var productPrice = $('product_price');
			var klarnaMonthlyCost = $('klarna_monthly_cost');
			var stockDetail = $('stock_detail');
			var buyButton = $('div_submit_buy_button');

			if (null != this.variations && 0 < this.variations.length) {
				var currentlyActiveVariationIndex = this.getActiveVariationIndex();

				if (null == currentlyActiveVariationIndex) {
					if (submitFormButton) {
						submitFormButton.disabled = true;
					}
					productItemId.innerHTML = '-';
					productPrice.innerHTML = '-';
					if (null != klarnaMonthlyCost) {
						klarnaMonthlyCost.innerHTML = '-';
					}
					if (null != stockDetail) {
						stockDetail.innerHTML = '-';
					}
					hiddenFieldVariationId.value = -1;
					if (buyButton) {
						buyButton.hide();
					}
					return;
				} else {
					// change submit_form_button value to selected variation id
					hiddenFieldVariationId.value = this.variations[currentlyActiveVariationIndex]['id'];
				}
			}

			var selectedProduct = this.getProductData();

			productItemId.innerHTML = selectedProduct['Webshopitem']['serial_number'];
			productPrice.innerHTML = selectedProduct['Webshopitem']['display_price'];

			var currentPrice = 0;
			var originalPrice = 0;

			var currentPriceField = $(this.groupIdPrefix + 'current_product_price_value');
			if (currentPriceField) {
				currentPrice = this.getProductPrice();
				currentPriceField.innerHTML = this.moneyRenderer(currentPrice);
			}

			var originalPriceField = $(this.groupIdPrefix + 'original_product_price_value');
			if (originalPriceField) {
				originalPrice = this.getProductPrice(false, true);
				originalPriceField.innerHTML = this.moneyRenderer(originalPrice);
				if (currentPrice == originalPrice) {
					originalPriceField.hide();
				} else {
					originalPriceField.show();
				}
			}

			if (null != klarnaMonthlyCost) {
				klarnaMonthlyCost.innerHTML = this.moneyRenderer(selectedProduct['Webshopitem']['klarna_monthly_cost']);
			}
			if (null != stockDetail) {
				stockDetail.innerHTML = selectedProduct['Webshopitem']['variation_stock_state'];
			}
			var resultingStockAmount = this.displayStockMinusReserved ? (selectedProduct['Webshopitem']['in_stock'] - selectedProduct['Webshopitem']['stock_reserved']) : selectedProduct['Webshopitem']['in_stock'];
			if ((0 < selectedProduct['Webshopitem']['price']) && (this.outOfStockShowCanBePurchased || ('REMOTE' == selectedProduct['Webshopitem']['stock_type']) || (0 < resultingStockAmount))) {
				if (buyButton) {
					buyButton.show();
				}
			} else {
				if (buyButton) {
					buyButton.hide();
				}
			}

			if ((null != this.variations) && (0 < this.variations.length)) {
				var newMainImage = false;
				if (selectedProduct['Images']) {
					newMainImage = selectedProduct['Images'];
				} else if (this.mainImage) {
					newMainImage = this.mainImage;
				}

				if (newMainImage) {
					$('main_product_image_link').title =  newMainImage['name'];
					$('main_product_image_link').href = newMainImage['url'];
					$('main_product_image').alt =  newMainImage['name'];
					$('main_product_image').src = newMainImage['main_src'];

					$('product_view_large_image').href = newMainImage['url'];

					previousVariationId = ((false === previousVariationId) && (0 != currentlyActiveVariationIndex)) ? this.variations[0]['id'] : previousVariationId;
					$('product_image_link_' + newMainImage['id']).style.display = 'none';
					for (var i in this.variations) {
						if (this.variations[i]['id'] == previousVariationId) {
							var previousImageId = this.variations[i]['Images'] ? this.variations[i]['Images']['id'] : this.mainImage['id'];
							if (previousImageId != newMainImage['id']) {
								$('product_image_link_' + previousImageId).style.display = '';
							}
							break;
						}
					}
				}
			}

			if (submitFormButton) {
				submitFormButton.disabled = false;
			}
		},
		onSelectionChange: function(attributeId, dontReset) {
			var init = true;

			this.setProductPrice(null);
			this.setProductData(null);
			var isAttributeVariation = ('VARIABLE' == this.attributes[this.attributeIdToKey(attributeId)].type)
			if (isAttributeVariation) {
				this.setActiveVariationIndex(null);
			}

			if ('undefined' == typeof(dontReset)) {
				dontReset = ((null != this.getActiveVariationIndex()) || (null == this.variations) || (0 == this.variations.length));
				init = false;
			}

			if (!this.hierarchy) {
				var variationList = this.getAttributeVariationList(attributeId, this.attributes[this.attributeIdToKey(attributeId)].getSelectedOption().value);
				this.selectValidVariation(variationList);
			}

			var disableWholeAttribute = false;
			var resetSelectedOption = false;

			var nonVariableAttributes = [];
			// Handling ONLY variable attributes first - they can alter the base price (variation) which is needed for calculating addon prices for the rest
			for (var currentAttributeIdKey in this.attributes) {
				var isCurrentAttributeVariable = ('VARIABLE' == this.attributes[currentAttributeIdKey].type)
				if (isCurrentAttributeVariable) {
					this.repaintAttribute(this.keyToAttributeId(currentAttributeIdKey), dontReset);

					if (!this.hierarchy || dontReset) {
						continue;
					}

					if (disableWholeAttribute) {
						this.attributes[currentAttributeIdKey].disable();
					} else {
						this.attributes[currentAttributeIdKey].enable();
					}

					if (resetSelectedOption) {
						this.attributes[currentAttributeIdKey].setSelectedOption(0);
					}

					if (0 == this.attributes[currentAttributeIdKey].getSelectedOption().value) {
						disableWholeAttribute = true;
						resetSelectedOption = true;
					}

					if (!resetSelectedOption && (attributeId == this.keyToAttributeId(currentAttributeIdKey))) {
						resetSelectedOption = true;
					}
				} else {
					nonVariableAttributes.push(this.keyToAttributeId(currentAttributeIdKey));
				}
			}

			// Handling ONLY NON variable attributes
			for (var i = 0; i < nonVariableAttributes.length; i++) {
				this.repaintAttribute(nonVariableAttributes[i], dontReset);
			}

			var previousVariationId = init ? false : this.getHistory();
			this.setHistory();
			this.updateProductView(previousVariationId);
		},
		selectValidVariation: function(variationList) {
			var currentSelectionIsValid = true;

			for (var i = 0; i < variationList.length; i++) {
				currentSelectionIsValid = true;
				for (var attributeIdKey in this.attributes) {
					if (('VARIABLE' == this.attributes[attributeIdKey].type) && variationList[i][this.keyToAttributeId(attributeIdKey)] != this.attributes[attributeIdKey].getSelectedOption().value) {
						currentSelectionIsValid = false;
						break
					}
				}

				if (currentSelectionIsValid) {
					break;
				}
			}

			if (currentSelectionIsValid) {
				return;
			}

			alert("You selected combination that is not supported, system will automaticaly find valid combination that match best with one you selected.");

			// Set first variation in a list as selected one
			for (var attributeIdKey in this.attributes) {
				if ('VARIABLE' == this.attributes[attributeIdKey].type) {
					this.attributes[attributeIdKey].setSelectedOption(variationList[0][this.keyToAttributeId(attributeIdKey)]);
				}
			}
		},
		getAttributeVariationList: function(attributeId, attributeValue) {
			var variationList = [];
			for (var i = 0; i < this.variationAttributesTable.length; i++) {
				if (attributeValue == this.variationAttributesTable[i][attributeId]) {
					variationList.push(this.variationAttributesTable[i]);
				}
			}

			return variationList;
		},
		repaintAttribute: function(attributeId, addPriceSuffix) {
			var validOptionsValues = {};
			if ('VARIABLE' != this.attributes[this.attributeIdToKey(attributeId)].type) {
				for (var i = 0; i < this.attributes[this.attributeIdToKey(attributeId)].options.length; i++) {
					var attributeOption = this.attributes[this.attributeIdToKey(attributeId)].options[i];
					var priceChange = this.getAttributevaluePriceChange(attributeId, attributeOption.value);
					validOptionsValues[attributeOption.value] = {priceChange: priceChange};
				}
			} else {
				var possibleOptions = this.getPossibleVariableAttributeOptions(attributeId);

				for (var i = 0; i < possibleOptions.length; i++) {
					var priceChange = this.getAttributevaluePriceChange(attributeId, possibleOptions[i].value);
					validOptionsValues[possibleOptions[i].value] = {priceChange: priceChange};
				}
			}
			this.attributes[this.attributeIdToKey(attributeId)].repaint(validOptionsValues, addPriceSuffix);
		},
		getAttributevaluePriceChange: function(attributeId, optionValue) {
			// Skip price change calculation for currently selected option
			var selectedOption = this.attributes[this.attributeIdToKey(attributeId)].getSelectedOption();
			if (optionValue == selectedOption.value) {
				return null;
			}

			var productPrice = this.getProductPrice();

			if ('VARIABLE' != this.attributes[this.attributeIdToKey(attributeId)].type) {
				var optionPriceAddon = this.attributes[this.attributeIdToKey(attributeId)].getOption(optionValue).getPriceAddon();
				return parseFloat(optionPriceAddon) - parseFloat(selectedOption.getPriceAddon());
			} else {
				var optionVariation = this.findVariationForAttributeOption(attributeId, optionValue);
				if (null == optionVariation) {
					return null;
				}

				var optionVariationPrice = this.getProductPrice(optionVariation);
				return parseFloat(optionVariationPrice) - parseFloat(productPrice);
			}
		},
		findVariationForAttributeOption: function(attributeId, optionValue) {
			var hashPattern = this.getVariationHashPattern(attributeId);
			var hash = this.getVariationHash(hashPattern, optionValue);

			var variationIndex = ('undefined' != typeof(this.variationAttributehashTable[hash]))? this.variationAttributehashTable[hash] : null;

			return (null != variationIndex) ? this.variations[variationIndex] : null;
		},
		moneyRenderer: function(value, params) {
			params = ('object' == typeof(params)) ? params : {};

			var currencySign = '';
			if (params.currency) {
				currencySign = params.currency.symbol ? params.currency.symbol : currencySign;
				currencySign = currencySign ? currencySign : (params.currency.code ? params.currency.code : currencySign);
			}
			currencySign = currencySign ? currencySign : this.webshopSettings['currency_symbol'];
			currencySign = currencySign ? currencySign : this.webshopSettings['currency_code'];

			if (currencySign) {
				params.prefix = currencySign + ' ';
			}

			if (!params.decimalPlaces) {
				params.decimalPlaces = this.localSettings.decimal_places;
			}

			if (!params.decimalSeparator) {
				params.decimalSeparator = this.localSettings.decimal_point;
			}

			if (!params.thousandsSeparator) {
				params.thousandsSeparator = this.localSettings.thousands_separator;
			}

			return Common.numberFormat(value, params);
		}
	}
};
Attributes.Attribute = function(config, attributeManager) {
	var attributeHtmlElement = $(attributeManager.groupIdPrefix + 'attribute_' + config['id']);

	var initOptions = function() {
		if ('undefined' == typeof(config['Attributevalue'])) {
			return [];
		}

		var selectedOption = null;
		if (attributeHtmlElement) {
			if ((0 <= attributeHtmlElement.selectedIndex) && (attributeHtmlElement.options.length > attributeHtmlElement.selectedIndex)) {
				selectedOption = attributeHtmlElement.options[attributeHtmlElement.selectedIndex];
			} else {
				selectedOption = attributeHtmlElement.options[0];
			}
		}

		var options = [];
		for (var i = 0; i < config['Attributevalue'].length; i++) {
			var newOption = new Attributes.AttributeOption(config['Attributevalue'][i], attributeManager);
			if (selectedOption && (selectedOption.value == newOption.value)) {
				newOption.selected = true;
			}

			options.push(newOption);
		}

		return options;
	};

	return {
		id: config['id'],
		type: config['ProductsAttribute']['type'],
		required: config['ProductsAttribute']['required'],
		attributeHtmlElement: attributeHtmlElement,
		options: initOptions(),
		invalidClass: 'invalid',
		attributeManager: attributeManager,
		getOption: function(value, returnHtmlElement) {
			if ('undefined' == returnHtmlElement) {
				returnHtmlElement = false;
			}

			var optionToReturn = null;
			for (var i = 0; i < this.options.length; i++) {
				if (value == this.options[i].value) {
					optionToReturn = this.options[i];
					break;
				}
			}

			if (optionToReturn && returnHtmlElement) {
				optionToReturn = this.getHtmlOptionElement(optionToReturn);
			}

			return optionToReturn;
		},
		getHtmlOptionElement: function(option) {
			return $(this.attributeManager.groupIdPrefix + 'attributeOption_' + this.id + '_' + option.value);
		},
		getSelectedOption: function() {
			var selectedOption = null;
			if (this.attributeHtmlElement) {
				selectedOption = this.attributeHtmlElement.options[this.attributeHtmlElement.selectedIndex];
			}

			return this.getOption(selectedOption.value);
		},
		setSelectedOption: function(optionValueToSelect) {
			this.unselectAll();
			var optionToSelect = this.getOption(optionValueToSelect);
			if (optionToSelect) {
				optionToSelect.selected = true;
				var htmlOptionElement = this.getHtmlOptionElement(optionToSelect);
				if (htmlOptionElement) {
					htmlOptionElement.selected = true;
				}
			}
		},
		unselectAll: function() {
			for (var i = 0; i < this.options.length; i++) {
				this.options[i].selected = false;
				var htmlOptionElement = this.getHtmlOptionElement(this.options[i]);
				if (htmlOptionElement) {
					htmlOptionElement.selected = false;
				}
			}
		},
		disable: function() {
			if (this.attributeHtmlElement) {
				this.attributeHtmlElement.disabled = true;
			}
		},
		enable: function() {
			if (this.attributeHtmlElement) {
				this.attributeHtmlElement.disabled = false;
			}
		},
		removeAllHtmlOptionsTags: function() {
			if (!this.attributeHtmlElement) {
				return;
			}

			while (0 < this.attributeHtmlElement.options.length) {
				this.attributeHtmlElement.remove(this.attributeHtmlElement.options.length - 1);
			}
		},
		appendHtmlOption: function(option, priceChange) {
			if (this.getHtmlOptionElement(option)) {
				return;
			}

			if (!this.attributeHtmlElement) {
				return;
			}

			var newOptionText = option.text;
			var newOptionTitle = false;
			if (0 != option.value) {
				if ((null == priceChange)) {
					newOptionText += ' *';
					newOptionTitle = "This option is unavaiable for current variation";
				} else if (this.attributeManager.displayPrices && (0 != priceChange)) {
					var formattedPrice = rawNumberFormat(
						priceChange,
						2,
						',',
						'.'
					)
					newOptionText += ' (' + ((0 > priceChange) ? '' : '+') + formattedPrice + ')';
				}
			}
			var newOption = new Option(newOptionText, option.value);
			newOption.id = this.attributeManager.groupIdPrefix + 'attributeOption_' + this.id + '_' + option.value;
			if (newOptionTitle) {
				newOption.setAttribute('title', newOptionTitle);
			}

			this.attributeHtmlElement.options[this.attributeHtmlElement.options.length] = newOption;
//          newOption.selected = option.selected;
		},
		repaint: function(validOptions, addPriceSuffix) {
			// IE can't simply hide options inside select, so we have to remove all options from select and rebuild select again with walid options
			var selectedOption = this.getSelectedOption();
			if (this.attributeManager.hideInvalidOptions) {
				this.removeAllHtmlOptionsTags();
			}

			for (var i = 0; i < this.options.length; i++) {
				if ((0 == this.options[i].value) || ('undefined' != typeof(validOptions[this.options[i].value]))) {
					var priceChange = ('undefined' != typeof(validOptions[this.options[i].value])) ? validOptions[this.options[i].value].priceChange : null;

					// Reset price change for currently selected option
					priceChange = (addPriceSuffix && (selectedOption.value != this.options[i].value)) ? priceChange : 0;
					this.appendHtmlOption(this.options[i], priceChange);
					this.removeOptionClass(this.options[i], this.invalidClass);
				} else {
					this.addOptionClass(this.options[i], this.invalidClass);
				}
			}

			this.setSelectedOption(selectedOption.value);
		},
		addOptionClass: function(option, className) {
			var htmlElement = this.getHtmlOptionElement(option);
			if (!htmlElement) {
				return;
			}

			if (className && !htmlElement.hasClassName(className)) {
				htmlElement.addClassName(className);
			}

			/*if (attributeManager.hideInvalidOptions && (0 != option.value)) {
				htmlElement.hide();
				htmlElement.style.visibility = 'hidden';
			}*/

			if (this.attributeManager.disableInvalidOptions && (0 != option.value)) {
				htmlElement.disabled = true;
			}
		},
		removeOptionClass: function(option, className) {
			var htmlElement = this.getHtmlOptionElement(option);
			if (!htmlElement || !className || !htmlElement.className) {
				return;
			}

			if (htmlElement.hasClassName(className)) {
				htmlElement.removeClassName(className);

				/*if (attributeManager.hideInvalidOptions) {
					htmlElement.show();
					htmlElement.style.visibility = 'visible';
				}*/

				if (this.attributeManager.disableInvalidOptions) {
					htmlElement.disabled = false;
				}
			}
		}
	}
};
Attributes.AttributeOption = function(config, attributeManager) {
	config.selected = ('undefined' == typeof(config.selected)) ? false : config.selected;
	return {
		text: config['name'],
		value: config['id'],
		originalPrice: config['AttributevaluesProductsAttribute']['original_price'],
		price: config['AttributevaluesProductsAttribute']['price'],
		priceType: config['AttributevaluesProductsAttribute']['price_type'],
		weight: config['AttributevaluesProductsAttribute']['weight'],
		weightType: config['AttributevaluesProductsAttribute']['weight_type'],
		selected: config.selected,
		attributeManager: attributeManager,
		getWeightAddon: function() {
			var productData = this.attributeManager.getProductData();
			var weightToReturn = 0;

			if (null != productData) {
				if ('AMOUNT' == this.weightType) {
					weightToReturn = this.weight;
				} else {
					var currentWeight = productData['Webshopitem']['weight'];
					weightToReturn = (currentWeight * this.weight) / 100;
				}
			}

			return weightToReturn;
		},
		getPriceAddon: function(productData, getOriginalPrice) {
			if ('undefined' == typeof(getOriginalPrice)) {
				getOriginalPrice = false;
			}

			var valueToTake = this.price;
			if (getOriginalPrice) {
				valueToTake = this.originalPrice;
			}
			return this.attributeManager.calculatePriceAddon(valueToTake, this.priceType, productData);
		}
	}
};

rawNumberFormat = function(number, decimals, dec_point, thousands_sep) {
	// http://kevin.vanzonneveld.net
	// +   original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
	// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	// +     bugfix by: Michael White (http://getsprink.com)
	// +     bugfix by: Benjamin Lupton
	// +     bugfix by: Allan Jensen (http://www.winternet.no)
	// +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
	// +     bugfix by: Howard Yeend
	// *     example 1: number_format(1234.5678, 2, '.', '');
	// *     returns 1: 1234.57

	var n = number, c = isNaN(decimals = Math.abs(decimals)) ? 2 : decimals;
	var d = dec_point == undefined ? '.' : dec_point;
	var t = thousands_sep == undefined ? ',' : thousands_sep, s = n < 0 ? '-' : '';
	var i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + '', j = (j = i.length) > 3 ? j % 3 : 0;

	return s + (j ? i.substr(0, j) + t : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, '$1' + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : '');
}

