Product.Options = Class.create();
Product.Options.prototype = {
	
	currentOptionsList : {},
	
    initialize : function(config,optionsList){
        this.config = config;
		this.optionsList = optionsList
		
		// If we run this before dom load, it won't show our prices
		$(document).observe('dom:loaded', function(){
			this.reloadPrice();
			
			$$('.product-options').first().removeClassName("loading");
		}.bind(this));
    },

	/**
	* This function gets run once on dom load.  It stores all of the options for a select list in a custom
	* property.  The rebuildOptions method uses this list to repopulate the select list when a conditional
	* select list changes
	*/
	storeOptions : function(){
		
		 $$('.product-custom-option').each(function(element){
            var optionId = 0;
            element.name.sub(/[0-9]+/, function(match){
                optionId = match[0];
            });
				
			hasConditionalOptions = false;
			if(element.type == 'select-one' || element.type == 'select-multiple') {
				element.store('options', []);
				$A(element.options).each(function(el){
					
					if(this.config[optionId][el.value] && this.config[optionId][el.value]['condition']){
						hasConditionalOptions = true;
						/*cl("option has conditionals: " + this.config[optionId][el.value]['title'] + ' Condition: ' + this.config[optionId][el.value]['condition']);*/
					}
					
					element.retrieve('options').push(el.cloneNode(true));
					//el.remove();
				}.bind(this));
				
			}
			// Remove the stored options for select lists that don't have conditional options
			if(!hasConditionalOptions)
				element.store('options', null);
			
			element.store('hasConditionalOptions', hasConditionalOptions ? true : false);
		}.bind(this));
		
	},

    reloadPrice : function(selectedEl){

		if(!Object.isUndefined(selectedEl)){
/*			cl(el);
			cl(el.name.match(/[0-9]+/));
			cl(this.config);
		
			if(this.config[el.name.match(/[0-9]+/)] && this.config[el.name.match(/[0-9]+/)]['title'] == "Size"){*/
			if(selectedEl.type == 'select-one')
				this.rebuildOptions(selectedEl);
/*			}*/
		}

        price = new Number();
        config = this.config;
        skipIds = [];
        $$('.product-custom-option').each(function(element){
            var optionId = 0;
            element.name.sub(/[0-9]+/, function(match){
                optionId = match[0];
            });
            if (this.config[optionId]) {
                if (element.type == 'checkbox' || element.type == 'radio') {
                    if (element.checked) {
                        if (config[optionId][element.getValue()]) {
                            price += parseFloat(config[optionId][element.getValue()]['price']);
                        }
                    }
                } else if(element.hasClassName('datetime-picker') && !skipIds.include(optionId)) {
                    dateSelected = true;
                    $$('.product-custom-option[id^="options_' + optionId + '"]').each(function(dt){
                        if (dt.getValue() == '') {
                            dateSelected = false;
                        }
                    });
                    if (dateSelected) {
                        price += parseFloat(this.config[optionId]['price']);
                        skipIds[optionId] = optionId;
                    }
                } else if(element.type == 'select-one' || element.type == 'select-multiple') {
                    if (element.options) {
	
	
                        $A(element.options).each(function(selectOption){
                            if (selectOption.selected) {
                                if (this.config[optionId][selectOption.value]) {
                                    price += parseFloat(this.config[optionId][selectOption.value]['price']);
                                }
                            }
                        });
                    }
                } else {
                    if (element.getValue().strip() != '') {
                        price += parseFloat(this.config[optionId]['price']);
                    }
                }
            }
        });
        try {
            optionsPrice.changePrice('options', price);
            optionsPrice.reload();
			this.changePricePerEach(price);
        } catch (e) {

        }
		return false;
    },

	changePricePerEach : function(price){
		
		try {
			qtyOptionId = opConfig.optionsList['Quantity'];
			qtyEl = $('select_' + qtyOptionId);
		
			if(!Object.isElement(qtyEl))
				throw "Can't find qty select list";
		
			qtyElValue = qtyEl.getValue();
		
			if(!opConfig.config[qtyOptionId] || !opConfig.config[qtyOptionId][qtyElValue] || !opConfig.config[qtyOptionId][qtyElValue]['title'])
				throw "Can't find qty values in the json object";
		
			qtyRaw = opConfig.config[qtyOptionId][qtyElValue]['title'];
			qty = parseInt(qtyRaw.replace(/[^0-9\.]/,''));
		
			if(qty <= 0)
				throw "The returned qty value is less than or equal to 0";
		
			pricePer = price / qty;
			pricePerFormatted = optionsPrice.formatPrice(pricePer);
		
			$('price_per_each').update('('+pricePerFormatted+' each)');
		} catch (e) {
			$('price_per_each').update('');
		}
	},

/*	These two functions were prototypes for trying to be able to just selectively add/remove options from select lists, as 
	opposed to rebuilding the options every time.  This code still needs a lot of work, if it's to be used.
	insertOption : function(option){
		
		this.currentOptionsList;
		this.currentOptionsStorageList;
		
		value = option.value;
		
		// If option already exists in select
		if(this.currentOptionsList[value])
			return true;
			
		var previousOption;
		this.currentOptionsStorageList.each(function(option){
			previousOptionStorage = option;
			if(option.value = value) // We've found our match, let's exit
				throw $break;
		});
		
		previousOption = this.currentOptionsList[previousOptionStorage.value]
		
		previousOption.insert({after:option});
	},
	
	removeOption : function(option){
		if(this.currentOptionsList[option.value]){
			this.currentOptionsList[option.value].remove();
			cl('removing option: ' option.value);
		}
	},
*/
	rebuildOptions : function(selectedEl){
		
        config = this.config;
		
		selectedSingles = {};
		// Populate selectedSingles object with all of the selected values for all the checkboxes so that
		// in case we need to hide a checkbox and show another with the same title due to a condition,
		// we can do so, since we'll know what was selected
		$$('.product-custom-option').each(function(element, index){
			
			var optionId = 0;
			element.name.sub(/[0-9]+/, function(match){
				optionId = match[0];
			});
            if (this.config[optionId]) {
        		if (element.type == 'checkbox' || element.type == 'radio') {
					elementTitle = (this.config[optionId][element.value]) ? this.config[optionId][element.value]['title'] : "";
					
					if(selectedSingles[elementTitle])
						return true;
					selectedSingles[elementTitle] = element.checked;
				}
			}
		}.bind(this));
		
		// This variable tracks to see if the first select box in the custom options is selected.  If it's not, all but the first select box are disabled
		firstOptionSelected = false; 
        $$('.product-custom-option').each(function(element, index){
			var optionId = 0;
			element.name.sub(/[0-9]+/, function(match){
				optionId = match[0];
			});
            if (this.config[optionId]) {
	
				// Disable all the options until the first option is selected
				if(index == 0){
					value = element.getValue();
					firstOptionSelected = (value && value.length) > 0 ? true : false;
				} else {
					if(!firstOptionSelected){
						element.up('td').addClassName('disabled');
						element.disable();
					} else {
						element.up('td').removeClassName('disabled');
						element.enable();
					}
				}
				if (element.type == 'checkbox' || element.type == 'radio') {
                    
					// Make sure the config value exists
					if(!this.config[optionId][element.value])
						return false;
						
					condition = this.config[optionId][element.value]['condition'];
					
					// If the option doesn't have a condition, then it should always show
					if(!condition)
						return false;
						
/*					cl("Found element.  Index: " + index + " Option ID: " + optionId + " Value: " + element.value);*/
					// Loop through all of the conditional segments to see if there is any reason 
					// why the option should NOT be shown
					show = true;
					condition.match(/([^&]+)/g).each(function(match){
						conditionParts = match.match(/([a-z\s]+)([=<>]+)(.+)/i);
						optionTitle = conditionParts[1];
						operator = conditionParts[2];
						thisValue = conditionParts[3];

						conditionalOptionId = this.optionsList[optionTitle];
						selectList = $('select_' + conditionalOptionId);

						if(selectList){
					        selectedValueId = selectList.getValue()
					        if(selectedValueId){ // Option value can't be blank
					        	if(this.config[conditionalOptionId][selectedValueId]['sku']) // If the sku exists, then base the conditional matching off of that
					        		conditionalValue = this.config[conditionalOptionId][selectedValueId]['sku']
					        	else if(this.config[conditionalOptionId][selectedValueId]['title']) // title is the default value to match against (the title from th json object, not the element's title)
					        		conditionalValue = this.config[conditionalOptionId][selectedValueId]['title']
					        	else
					        		conditionalValue = 0;

					        } else {
					        	conditionalValue = 0;
					        }
						} else {
					        conditionalValue = 0;
						}

						// Since the matching is AND, if the condition doesn't match, then show must be false
						if(!this.checkCondition(thisValue,conditionalValue,operator)){
					        show = false; 
					        throw $break;
						}
					}.bind(this));
					if(show){
						element.up('li').show();
						// If a different checkbox with the same title was checked, then check this checkbox
						elementTitle = (this.config[optionId][element.value]) ? this.config[optionId][element.value]['title'] : "";
						element.checked = (selectedSingles[elementTitle]) ? true : false;
						if(selectedSingles[elementTitle])
							cl("CHECKING this checkbox: " + elementTitle);
					} else { 
						element.up('li').hide();
						element.checked = false; // We must uncheck all hidden options, for obvious reasons
					}
                }
                else if(element.type == 'select-one' || element.type == 'select-multiple') {
	
					// If select list doesn't have options with conditional display settings, then skip this select list
					if(element.retrieve('hasConditionalOptions')){
	
						selectedValue = element.getValue();
						selectedValue = (this.config[optionId][selectedValue]) ? this.config[optionId][selectedValue]['title'] : "";
					
						// Remove all of the options, since we're going to add the ones that match their condition later in the code
						$A(element.options).each(function(selectOption){
							if(Object.isElement(selectOption))
								selectOption.parentNode.removeChild(selectOption)
								// For some reason, this errored out in IE8, we have to use the oldschool method above
								// selectOption.remove();
						})
				
						element.retrieve('options').each(function(selectOption,index){

							// If the option doesn't have a value attribute, then insert it (eg: "--Please Select--" options)
							if(!this.config[optionId][selectOption.value]){
								element.insert(selectOption.cloneNode(true));
								return;
							}
						
							condition = this.config[optionId][selectOption.value]['condition'];
					
							if(!condition){
								element.insert(selectOption.cloneNode(true));
								return;
							}
					
/*							cl("Looping element.  Index: " + index + " Option ID: " + optionId + " Value: " + selectOption.value);*/
						
							show = true;
							condition.match(/([^&]+)/g).each(function(match){
								conditionParts = match.match(/([a-z\s]+)([=<>]+)(.+)/i);
								optionTitle = conditionParts[1];
								operator = conditionParts[2];
								thisValue = conditionParts[3];

								conditionalOptionId = this.optionsList[optionTitle];
								selectList = $('select_' + conditionalOptionId);

								if(selectList){
							        selectedValueId = selectList.getValue()

							        if(selectedValueId){ // Option value can't be blank
							        	/*cl('conditionalOptionId:'+conditionalOptionId+"  selectedValueId:"+selectedValueId)*/
							        	if(this.config[conditionalOptionId][selectedValueId]['sku'])
							        		conditionalValue = this.config[conditionalOptionId][selectedValueId]['sku']
							        	else if(this.config[conditionalOptionId][selectedValueId]['title'])
							        		conditionalValue = this.config[conditionalOptionId][selectedValueId]['title']
							        	else
							        		conditionalValue = false;

							        } else {
							        	conditionalValue = 0;
							        }
								} else {
							        conditionalValue = 0;
								}

								// Since the matching is AND, if the condition doesn't match, then show must be false
								if(!this.checkCondition(thisValue,conditionalValue,operator)){
							        show = false; 
							        return false;
								}
							}.bind(this));

							if(show){
								element.insert(selectOption.cloneNode(true));
							}
						}.bind(this));

						// If a different option with the same title was checked, then select this option
						$A(element.options).each(function(selectOption,index){
							if(selectOption.value && this.config[optionId][selectOption.value]['title'] == selectedValue){
/*								cl("Setting index to: " + index + " Title value: " + this.config[optionId][selectOption.value]['title'])*/
								element.selectedIndex = index;
							
								priceRaw = this.config[optionId][selectOption.value]['price_formatted'];
								price = parseFloat(priceRaw.replace(/[^0-9\.]/,''));
								if(price > 0)
									$('option_price_'+optionId).update(priceRaw);
								else
									$('option_price_'+optionId).update('');
							}
						});
					} // If a select list doesn't have conditional options, we still need to loop through it
					else if(selectedEl && selectedEl.getValue() == element.getValue())
					{
						elementValue = element.getValue();

						$A(element.options).each(function(selectOption,index){
							if(selectOption.value.length <= 0)
								return;
							if(selectOption.value == elementValue){
								element.selectedIndex = index;

								priceRaw = this.config[optionId][selectOption.value]['price_formatted'];
								price = parseFloat(priceRaw.replace(/[^0-9\.]/,''));
								if(price > 0)
									$('option_price_'+optionId).update(priceRaw);
								else
									$('option_price_'+optionId).update('');
							}
						});						
					}
					
					if($A(element.options).length <= 0 || ($A(element.options).length == 1 && $A(element.options).first().value == '')) {
						element.up('td').addClassName('disabled');
						element.disable();
					} else {
						element.up('td').removeClassName('disabled');
						element.enable();
					}
					
				}
            }
        }.bind(this));
	},
	
	checkCondition : function(thisValue,conditionalValue,operator){
		// Convert to strings so we can use replace() method
		conditionalValue = conditionalValue+"";
		thisValue = thisValue+"";
		switch(operator){
			case ">":
				return (parseInt(conditionalValue.replace(/[^0-9]/,'')) > parseInt(thisValue.replace(/[^0-9]/,'')))
				break;
			case '>=':
				return (parseInt(conditionalValue.replace(/[^0-9]/,'')) >= parseInt(thisValue.replace(/[^0-9]/,'')))
				break;
			case "<":
				return (parseInt(conditionalValue.replace(/[^0-9]/,'')) < parseInt(thisValue.replace(/[^0-9]/,'')))
				break;
			case '<=':
				return (parseInt(conditionalValue.replace(/[^0-9]/,'')) <= parseInt(thisValue.replace(/[^0-9]/,'')))
				break;
			case '=':
				return (conditionalValue == thisValue)
				break;
			case '==':
				return (parseInt(conditionalValue.replace(/[^0-9]/,'')) == parseInt(thisValue.replace(/[^0-9]/,'')))
				break;
			default:
				cl('Could not find match for operator: "' + operator + '" thisValue: ' + thisValue);
				return true;
				break;
		}
	}
}