/**
(C) Copyright MarketLive. 2006. All rights reserved.
MarketLive is a trademark of MarketLive, Inc.
Warning: This computer program is protected by copyright law and international treaties.
Unauthorized reproduction or distribution of this program, or any portion of it, may result
in severe civil and criminal penalties, and will be prosecuted to the maximum extent
possible under the law.


(SDC 2009-12-21) Moved Stock Message to .p2p.detail.itemtablerow.tile. Uses oMessagingText1 to populate remote var, myStockMessage
(SDC 2010-01-08) Display price in different item table row location if product contains multiple sku prices. Commented out price in select option
(SDC 2010-01-11) Manipulate hero and Shown In... text only if no item table row thumbnail exists for this product (ie. is family with 2+ members)
(SDC 2010-04-05) Added error handling for multiple dependent option menus
(SDC 2010-05-11) Added default stock message for multi-skued items
(SDC 2010-06-29) Changed the above to show first stock messaging if all sku availability messaging is the same
(SDC 2010-08-16) If an option is selected from the first menu, filter dependent skus
(SDC 2010-08-16) Adust hero or thumb image on selection where applicable
(SDC 2010-08-24) Commented out all swatch syncing calls (not needed)
(SDC 2010-10-05) Update the alternate image only if there is more than one color option

*/

// (SDC 2010-04-05) Trim function used in error handling for multiple dependent option menus
String.prototype.trim = function () { return this.replace(/^\s*/, "").replace(/\s*$/, ""); }


/**
 * DependentOptionMenus class client-side definition encapsulates option menus
 * who values are dynamically filled in as selections are made from previous
 * menus.  Also includes messaging for SKU availability and/or price.
 *
 * @param {array} aOptionTypes array of MLOptionType objects
 * @param {array} aOptionSkus array of MLOptionsSku objects
 * @param {boolean} bDoMsgAvailNoSku no sku messaging flag
 * @param {boolean} bDoMsgAvailInStock in-stock messaging flag
 * @param {boolean} bDoMsgAvailBackOrdered back-ordered messaging flag
 * @param {boolean} bDoMsgAvailOutOfStock out-of-stock messaging flag
 * @param {boolean} bDoMsgPrice price messaging flag
 * @param {boolean} bDoMsgAvailInMenu availability in menu or outside flag
 * @param {boolean} bDoMsgPriceInMenu price in menu or outside flag
 * @param {String} sMessageNoSku no sku message
 * @param {String} sMessageInStock in-stock message
 * @param {String} sMessageBackOrdered back-ordered message (includes {0} date replacement token)
 * @param {String} sMessageOutOfStock out-of-stock message
 * @param {String} sOptionsSeparator separator character for intra-option value/messaging/price
 * @param {String} sAvailabilityVaries default stock message for multi-skued items
 * @param {array} aLargeImages array of product page hero images (SDC 2010-08-18)
 * @param {array} aThumbnailImages array of product page family thumbnail images (SDC 2010-08-18)
 * @param {boolean} bHasMultipleColors has multiple colors or not (SDC 2010-10-05)
 */
function DependentOptionMenus(iProductPk,
                              aOptionTypes,
                              aOptionSkus,
                              bDoMsgAvailNoSku,
                              bDoMsgAvailInStock,
                              bDoMsgAvailBackOrdered,
                              bDoMsgAvailOutOfStock,
                              bDoMsgPrice,
                              bDoMsgAvailInMenu,
                              bDoMsgPriceInMenu,
                              sMessageNoSku,
                              sMessageInStock,
                              sMessageBackOrdered,
                              sMessageOutOfStock,
                              sOptionsSeparator,
							  sAvailabilityVaries,
                              aAltLargeImages,
                              aAltThumbnailImages,
                              bHasMultipleColors) {

  this.iProductPk             = iProductPk;
  this.aOptionTypes           = aOptionTypes;
  this.aOptionSkus            = aOptionSkus;
  this.bDoMsgAvailNoSku       = bDoMsgAvailNoSku;
  this.bDoMsgAvailInStock     = bDoMsgAvailInStock;
  this.bDoMsgAvailBackOrdered = bDoMsgAvailBackOrdered;
  this.bDoMsgAvailOutOfStock  = bDoMsgAvailOutOfStock;
  this.bDoMsgPrice            = bDoMsgPrice;
  this.bDoMsgAvailInMenu      = bDoMsgAvailInMenu;
  this.bDoMsgPriceInMenu      = bDoMsgPriceInMenu;
  this.sMessageNoSku          = sMessageNoSku;
  this.sMessageInStock        = sMessageInStock;
  this.sMessageBackOrdered    = sMessageBackOrdered;
  this.sMessageOutOfStock     = sMessageOutOfStock;
  this.sOptionsSeparator      = sOptionsSeparator;
  this.sAvailabilityVaries    = sAvailabilityVaries;
  this.aAltLargeImages        = aAltLargeImages;
  this.aAltThumbnailImages    = aAltThumbnailImages;
  this.bHasMultipleColors     = bHasMultipleColors;
  

  // Maintains option type and option value requested to sync menus with (ie. from swatch click).
  this.requestChangeOptionTypePk = -1;
  this.requestChangeOptionPk = -1;
  
  // Stores the last price break request
  this.lastPriceBreakRequest = null;

  /**
   * Returns the option type in our array of option types.
   * @param {int} iOptionTypePk option type PK
   * @return {object} OptionType object
   */
  DependentOptionMenus.prototype.getOptionType = function(iOptionTypePk) {
    for (var i = 0; i < this.aOptionTypes.length; i++) {
      if (this.aOptionTypes[i].iPk == iOptionTypePk) {
        return this.aOptionTypes[i];
      }
    }

    // Not found.
    return null;
  }

  /**
   * Returns the index of the option type in our array
   * of option types.
   * @param {int} iOptionTypePk option type PK
   * @return {int} index >= 0 if found, else -1
   */
  DependentOptionMenus.prototype.getOptionTypeIndex = function(iOptionTypePk) {
    for (var i = 0; i < this.aOptionTypes.length; i++) {
      if (this.aOptionTypes[i].iPk == iOptionTypePk) {
        return i;
      }
    }

    // Not found.
    return -1;
  }

  /**
   * Returns the select menu object corresponding to an option type.
   * @param {int} iOptionTypePk option type PK
   * @return {object} DOM select object
   */
  DependentOptionMenus.prototype.getSelectObj = function(iOptionTypePk) {
    return document.getElementById('options_' + this.iProductPk + '_' + iOptionTypePk);
  }

  /**
   * Return one sku which matches the options
   * @param {array} aOptions array of Options objects to match against sku options
   * @return {object} OptionsSku object if found, else null
   */
  DependentOptionMenus.prototype.findSku = function(aOptions) {

    // Special case to return the single SKU when no options passed in and we only have 1 SKU.
    if (aOptions.length == 0 && this.aOptionSkus.length == 1) {
      return this.aOptionSkus[0];
    }

    // Go through each of the SKUs
    // TODO: Use Binary search.
    for (var i = 0; i < this.aOptionSkus.length; i++) {

      // Assume matches until proven otherwise.
      var skuMatched = true;

      // Compare the sku options with the array of options
      // passed in.
      var skuOptions = this.aOptionSkus[i].aOptions;
      
      // All of the options must be specified in the input
      // aOptions parameter.
      if (skuOptions.length != aOptions.length) {
        continue;
      }

      for (var j = 0; j < skuOptions.length; j++) {
        if (skuOptions[j].iPk != aOptions[j].iPk) {
          skuMatched = false;
          break;
        }
      }

      // If sku options matched, return it.
      if (skuMatched) {
        return this.aOptionSkus[i];
      }
    }

    return null;
  }

  /**
   * Get the availability messaging (in-stock, back-ordered, out of stock)
   * The constructed message is based on the configuration settings
   * controlling which types of availability messages to present.
   * @param {object} oSku OptionsSku sku object
   * @return {String} availability messaging text
   */
  DependentOptionMenus.prototype.getAvailabilityMessage = function(oSku) {
    var sMessage = '';

    if (!oSku) {
      if (this.bDoMsgAvailNoSku) {
        sMessage = this.sMessageNoSku;
      }
    }
    else if (oSku.bInStock) {
      if (this.bDoMsgAvailInStock) {
        sMessage = this.sMessageInStock;
      }
    }
    else if (oSku.sReorderDate.length > 0) {
      if (this.bDoMsgAvailBackOrdered) {
        var sBackOrder = this.sMessageBackOrdered;
        sBackOrder = sBackOrder.replace('{0}', oSku.sReorderDate);
        sMessage = sBackOrder;
      }
    }
    else {
      if (this.bDoMsgAvailOutOfStock) {
        sMessage = this.sMessageOutOfStock;
      }
    }

    return sMessage;
  }

  /**
   * Get the availability messaging and option price messaging for a
   * sku which matches the chosen options.
   * @param {array} aChosenOptions array of Option objects
   * @bForMenu {boolean} bForMenu true if want messaging for inside a menu, false for outside.
   * @return {String} messaging text
   */
  DependentOptionMenus.prototype.getMessaging = function(aChosenOptions, bForMenu) {
    var sMessage = '';

    // Find the skus that match those options.
    var oFoundSku = this.findSku(aChosenOptions);

    if ((bForMenu && this.bDoMsgAvailInMenu) ||
        (!bForMenu && !this.bDoMsgAvailInMenu)) {

      sMessage = this.getAvailabilityMessage(oFoundSku);
    }

    if ((bForMenu && this.bDoMsgPriceInMenu) ||
        (!bForMenu && !this.bDoMsgPriceInMenu)) {

      if (this.bDoMsgPrice && oFoundSku) {
        if (sMessage.length > 0) {
          // (SDC 2010-01-08) Commented out
          // sMessage += this.sOptionsSeparator;
        }
        // (SDC 2010-01-08) Commented out
        // sMessage += oFoundSku.sPrice;
      }
    }
	
    // (SDC 2010-01-08) Display price in different item table row location if product contains multiple sku prices
    var oSkuPriceDiv = document.getElementById('skuPrice_'+iProductPk); 
    var oProductPriceDiv = document.getElementById('productPrice_'+iProductPk);
    var sSkuPrice = new String(oProductPriceDiv.innerHTML);
    var bShowSkuPrice = false;

	// (SDC 2010-04-05, fix) Added error handling for multiple dependent option menus 
	if(oFoundSku){
		var sFoundSkuPrice = new String(oFoundSku.sPrice);
		sFoundSkuPrice = sFoundSkuPrice.trim();
		sSkuPrice = sSkuPrice.trim();
		
		if(sSkuPrice != oFoundSku.sPrice){
		  bShowSkuPrice = true;
		}
		
		if(oSkuPriceDiv && bShowSkuPrice){
		  oSkuPriceDiv.innerHTML = oFoundSku.sPrice;
		}
	}

    return sMessage;
  }

  /**
   * Build an array of Option objects representing the choices made in
   * select option menus.
   * @return {array} array of Option objects
   */
  DependentOptionMenus.prototype.buildChosenOptions = function() {
    var aChosenOptions = new Array();

    // Go through options that are selected and
    // build array of options that were chosen in those menus.
    //
    for (var i = 0; i < this.aOptionTypes.length; i++) {
      var oSelected = this.getSelectObj(this.aOptionTypes[i].iPk);

      // If <select> has a valid value, push it.
      if (oSelected.value > 0) {
        aChosenOptions.push(this.aOptionTypes[i].getOptionByPk(oSelected.value));
      }
      // Else, no more valid selections, done.
      else {
        break;
      }
    }

    return aChosenOptions;
  }

  /**
   * Clear the dynamic entries in a select option menu.  This means
   * all values except the static text option in the first index.
   * @param {object} oSelect DOM select object
   */
  DependentOptionMenus.prototype.clearOptionMenu = function(oSelect) {
    // Delete current options except for the first static item
    // Note: Delete in reverse order.
    for (var i = oSelect.options.length - 1; i > 0; i--) {
      oSelect.options[i] = null;
    }

    // This hack is needed to convince IE to recalc the
    // width of the select element after we remove all the
    // items.
    // TODO: Is there an easier elem.recalc() or something method?
    var oOptionElem = document.createElement("OPTION");
    oOptionElem.value = 0;
    oOptionElem.text = "";
    
    oSelect.options[oSelect.length] = oOptionElem;
    oSelect.options[1] = null;

    // Select the first static item.
    oSelect.value = 0;
  }

	  /**
	   * Dynamically load a select option menu with values corresponding
	   * to each option value in the option type for that menu.  If the
	   * menu is the final select menu, messaging can be added to the
	   * menu value text.
	   * @param {object} oSelect DOM select object
	   * @param {object} oOptionType OptionType object
	   * @param {int} iOptionTypeIndex index of the option menu being loaded (zero-based)
	   * @param {int} iChosenValue pk of the select menu option chosen by the user (SDC 2010-07-29) 
	   */
	  DependentOptionMenus.prototype.loadOptionMenu = function(oSelect, oOptionType, iOptionTypeIndex, iChosenValue) {

    // Save off current menu value so we can restore.
//    var sOrigValue = oSelect.value;
    var sOrigValue = iChosenValue;

    // Get the options values for this option type to load into menu.
    var aOptions = oOptionType.aOptions;
    
    this.clearOptionMenu(oSelect);   
    
    // (SDC 2010-08-17) Filter following dependent menu only if an option from the first menu was selected
    if (iChosenValue != 0 && iOptionTypeIndex == 1 && this.aOptionTypes.length > 1) {
    	
	    var aValidSkus=[];
	    for (var i=0; i < this.aOptionSkus.length; i++) {
	    	var sku = this.aOptionSkus[i];
	    	if(sku.iParentPk == iChosenValue) {
	    		aValidSkus.push(sku.aOptions[1]);
	    	}	
	    }
	    aOptions = aValidSkus;
    }
    
    // Assume not loading last menu, so no messaging.
    var bAddMessaging = false;
    var aChosenOptions = null;

    // If this is the last menu and we're showing messaging
    // in the menu, build up the array of options chosen in
    // the preceding menus as we will need them to add
    // messaging in the last menu's option value strings.
    //
    if (iOptionTypeIndex == this.aOptionTypes.length - 1 &&
         (this.bDoMsgAvailInMenu || this.bDoMsgPriceInMenu)) {

      bAddMessaging = true;

      // Build array of current <select> chosen values.
      aChosenOptions = this.buildChosenOptions();
    }

    // Add option menu for each option.
    for (var i = 0; i < aOptions.length; i++) {

      var iNewOptionPk = aOptions[i].iPk;
      var sNewOptionText = aOptions[i].sName;

      if (bAddMessaging) {
        // Temporarily push on this option value as chosen just
        // to get messaging.
        aChosenOptions.push(oOptionType.getOptionByPk(iNewOptionPk));

        // Add messaging text for these options.
        var sMsg = this.getMessaging(aChosenOptions, true);

        if (sMsg.length > 0) {
          sNewOptionText += this.sOptionsSeparator;
          sNewOptionText += sMsg;
        }

        // Remove temporary option choice.
        aChosenOptions.pop();
      }

      var oOptionElem = document.createElement("OPTION");

      oOptionElem.value = iNewOptionPk;
      oOptionElem.text = sNewOptionText;

      oSelect.options[oSelect.length] = oOptionElem;
      // Restore selected item.
      oSelect.value = sOrigValue;
    }
  }

  /**
   * Update state of menu(s) after a change to an option menu.  This may
   * include clearing or loading subsequent option menus.   *
   * @param {object} oSelect DOM select object
   * @param {int} iOptionTypePk pk of the option type of the option menu
   * @param {int} iOptionTypeIndex index of the option menu (zero-based)
   * @param {int} iSelectedIndex index of the option chosen (zero-based) (SDC 2010-08-19)
   */
  DependentOptionMenus.prototype.optionChanged = function(oSelect, iOptionTypePk, iOptionTypeIndex, iSelectedIndex) {
		  
	// (SDC 2010-08-16) If an option is selected from the first menu, clear any dependent sku price showing + adust hero or thumb where applicable
	if(iOptionTypeIndex == 0 && this.aOptionTypes.length != 1) {
		
		// Clear dependent menu sku price if applicable
		var oSkuPrice = document.getElementById("skuPrice_" + this.iProductPk);
		oSkuPrice.innerHTML = '';
		
		// Adust alternate hero or family thumbnail
		var oThumb = document.getElementById('thumb_'+this.iProductPk);
		
		// Update the alternate image, (SDC 2010-10-05) ...only if there is more than one color option
		if( this.bHasMultipleColors ) {
			this.setAlternateImage(oThumb, iSelectedIndex);
		}
		
		// Update Shown In... text if not a family member
		if ( iSelectedIndex != 0 && !oThumb ) {
			this.setShownInText(oSelect, iSelectedIndex); 
		}
	
	}
	  
    // Updates the hidden optionTypeValues_${optionTypePk} field.
    optionTypeValues(oSelect);

    // Get value that select was just changed to.
    var iPrevMenuValue = oSelect.value;

    // Assume all menus have values.
    var bAllOptionsSet = iPrevMenuValue > 0;

    // Go through subsequent menus.
    for( var i = iOptionTypeIndex + 1; i < this.aOptionTypes.length; i++ ) {

      // Get the next option type.
      var oOptionType = this.aOptionTypes[i];

      // Get corresponding <select> element.
      var oNextSelect = this.getSelectObj(oOptionType.iPk);

      // If the menu preceding this select is in its default value, clear this menu.
      if (iPrevMenuValue == 0) {
        this.clearOptionMenu(oNextSelect);

        // Try and sync swatches with this change.
        // (SDC 2010-08-19) Commented out
        // this.syncSwatches(oOptionType.iPk, oNextSelect.value);

        // Updates the hidden optionTypeValues_${optionTypePk} field.
        optionTypeValues(oNextSelect);
      }
      // Else, a valid menu selection was made.
      else {

      	// (SDC 2010-07-29) Moved outside if statement (below). Added oSelect.value param
        this.loadOptionMenu(oNextSelect, oOptionType, i, oSelect.value);
        
    	// Only load the menu if not already loaded or if it is the last menu and we're showing messaging in the menu.
        // (SDC 2010-07-29) Commented out to load dependent menus every time to allow for filtering
    	// if (oNextSelect.options.length == 1 || (i == this.aOptionTypes.length - 1 && (this.bDoMsgAvailInMenu || this.bDoMsgPriceInMenu))) {

          // If this option type was requested to be set to a specific
          // value (ie. from swatch click), set it now after the load.
          //
          if (oOptionType.iPk == this.requestChangeOptionTypePk) {

            oNextSelect.value = this.requestChangeOptionPk;

            // Clear the set request.
            this.requestChangeOptionTypePk = -1;
            this.requestChangeOptionPk = -1;
          }

          // Try and sync swatches with this change.
          // (SDC 2010-08-19) Commented out
          // this.syncSwatches(oOptionType.iPk, oNextSelect.value);

          // Updates the hidden optionTypeValues_${optionTypePk} field.
          optionTypeValues(oNextSelect);

          // (SDC 2010-07-29) Commented out to load dependent menus every time to allow for filtering
          // }
      }

      if (oNextSelect.value < 1) {
        bAllOptionsSet = false;
      }

      iPrevMenuValue = oNextSelect.value;
    }

		// Try to sync the price breaks tile
		this.syncPriceBreaks(this.buildChosenOptions(), bAllOptionsSet);

    // If not doing availability or messaging inside the menu,
    // update messaging text.
    if (!this.bDoMsgAvailInMenu || !this.bDoMsgPriceInMenu) {

      //var oMessagingText = document.getElementById('messagingText_' + this.iProductPk);
      var oMessagingText1 = document.getElementById('sdcMessagingText_' + this.iProductPk);

      if (oMessagingText1) {
        if (bAllOptionsSet) {
          // Return messaging for these options.
          var sMessaging = this.getMessaging(this.buildChosenOptions(), false);
          oMessagingText1.innerHTML = sMessaging;
          //oMessagingText.innerHTML = sMessaging;
          //oMessagingText.style.display="inline";
        }
        else {
          oMessagingText1.innerHTML = '';
          //oMessagingText.innerHTML = '';
          //oMessagingText.style.display="none";
        }
      }
    }
  }

  /**
   * Try and sync the swatches tile with a change to our menus.  If the option type PK
   * corresponds to the swatch object, it will be found and sent the synchronize method
   * passing in the new value that the swatch should adjust to.
   *
   * @param {int} iOptionTypePk pk of the option type of the option menu
   * @param {String} sSelectValue new value of the option menu
   */
  DependentOptionMenus.prototype.syncSwatches = function(iOptionTypePk, sSelectValue) {
    // Try and find swatch object corresponding to this option type by matching goSwatches_ + product pk + option type pk.
    
	// (SDC 2010-08-24) Commented out
	/*
    try {
      // (SDC 2010-01-11) Manipulate hero and Shown In... text only if no item table row thumbnail exists for this product (ie. is family)
      var oThumb = document.getElementById('thumb_'+this.iProductPk);
      if(!oThumb) {
	      var oSwatches = eval('goSwatches_' + this.iProductPk + '_' + iOptionTypePk);
	      oSwatches.synchronize(sSelectValue);
	    }
    }
    catch (e) {
    }
    */
  }

  /**
   * Event handler for select option menu changed value.  Updates
   * state of menu(s) and optionally synchronizes related swatch object.
   * @param {object} oSelect DOM select object
   * @param {int} iOptionTypePk pk of the option type of the option menu
   * @param {int} iOptionTypeIndex index of the option menu (zero-based)
   * @param {string} sSelectionDetails pipe-delimited string of user selection details to split (SDC 2010-08-19)
   */
  DependentOptionMenus.prototype.selectMenuChanged = function(oSelect, iOptionTypePk, iOptionTypeIndex, sSelectionDetails) {

	// (SDC 2010-08-19) Split user-selected details
	var aSelectionDetails = new Array();
	aSelectionDetails = sSelectionDetails.split("|");
	
	var iSelectedIndex = 0;
	var iSelectedValue = 0;
	iSelectedIndex = aSelectionDetails[0];
	iSelectedValue = aSelectionDetails[1];
	
    // Perform update after a menu changed.
    this.optionChanged(oSelect, iOptionTypePk, iOptionTypeIndex, iSelectedIndex);

    // Try and sync swatches with this change.
    // (SDC 2010-08-19) Commented out
//    this.syncSwatches(iOptionTypePk, oSelect.value);
  }
  
  /**
   * Try and sync the price breaks tile with a change to our menus.  If the all the
   * options have been set and a sku can be resloved, update the tile with sku specific
   * information, otherwise fall back to generic product information.
	 * @param {array} aChosenOptions array of Option objects
   * @param {boolean} bAllOptionsSet true if all options have been set, false if not.
   */  
  DependentOptionMenus.prototype.syncPriceBreaks = function(aChosenOptions, bAllOptionsSet) {
		// Set up dom pointer objects and refs
    var sPriceBreakID = "priceBreaks_" + this.iProductPk;    
    var oPriceBreakDOM = document.getElementById(sPriceBreakID);

    // Only continue if we've got a price break tile to update for this product.
    if (oPriceBreakDOM) {
			// Find the skus that match those options.
	    var oFoundSku = this.findSku(aChosenOptions);
	    
	    // Only coninue to a sku specific tile if all the options are set and we have a resloved sku 
	    if (bAllOptionsSet && oFoundSku){
	    	var sRequest = ("/priceBreaks.do?prodID=" + this.iProductPk +"&skuID=" + oFoundSku.iPk);
	    	// Only update the tile if it's a new request.
	    	if (this.lastPriceBreakRequest != sRequest){
	    		updateTileDisplay(sPriceBreakID, sRequest);
	    		this.lastPriceBreakRequest = sRequest;
	    	}
	    
	    // Continue to a product generic tile. 	    	
	    } else {
	    	var sRequest = ("/priceBreaks.do?prodID=" + this.iProductPk);
	    	// Only update the tile if it's a new request.
	    	if (this.lastPriceBreakRequest != sRequest){
	    		updateTileDisplay(sPriceBreakID, sRequest);
	    		this.lastPriceBreakRequest = sRequest;
	    	}
	    }	    	    
	  }
  }  

  /**
   * Try and sychronize our menu with an option value
   * selected via another UI element (ie. swatch clicked).  If
   * the menu cannot be synchronized at this time because prior
   * dependent menus have not been loaded, we record the request
   * and apply it when the menu is loaded.
   * @param {int} iOptionTypePk pk of the option type to sync
   * @param {int} iOptionPk pk of the option value fo select in the option type menu
   */
  DependentOptionMenus.prototype.synchronize = function(iOptionTypePk, iOptionPk) {
    // Get corresponding <select> menu object.
    var oSelect = this.getSelectObj(iOptionTypePk);

    if (oSelect != null) {

      // If the select has been loaded, we can set its new value.
      if (oSelect.options.length > 1) {

        if (oSelect.value != iOptionPk) {
          // Update value of select menu.
          oSelect.value = iOptionPk;
          
          // Notify of option change similar to when user clicks menu.
          // (SDC 2010-08-24) Added iSelectedIndex param to be used to filter additional dependent menus (if applicable)
          this.optionChanged(oSelect, iOptionTypePk, this.getOptionTypeIndex(iOptionTypePk), oSelect.options.selectedIndex);
        }
      }
      // Else, save off request and set when possible.
      else {
        this.requestChangeOptionTypePk = iOptionTypePk;
        this.requestChangeOptionPk = iOptionPk;
      }
    }
  }
  
  
  // ------------------------- BEGIN Sundance custom methods ------------------------- // 
  
  
  /**
   * (SDC 2010-08-19) Change the Shown In... text near the product page hero image.
   * @param (object) oSelect the select menu chosen by the user
   * @param (int) iSelectedIndex the index of the option chosen
   */
  DependentOptionMenus.prototype.setShownInText = function(oSelect, iSelectedIndex) {

	var oShownIn = document.getElementById('optionTextNearDetailImage');
	var oSelectedOption = oSelect.options[iSelectedIndex];
	
	oShownIn.innerHTML = "Shown in: "+oSelectedOption.text; 
	
  }

  /**
   * (SDC 2010-08-24) Change the product page hero or family thumbnail image.
   * @param (object) oThumb thumbnail object, determines either 'hero' or 'thumbnail' image type
   * @param {int} iSelectedIndex index of the option chosen (zero-based)
   */
  DependentOptionMenus.prototype.setAlternateImage = function(oThumb, iSelectedIndex) {

	  // TODO: populate this.sImagePath
	  
	  if ( !oThumb ) {
			
			// Update the large image
			var oLargeImage = document.getElementById('largeImage');
			var sLargeImagePath = "http://ii-prod-rw.marketlive.com/sundance/images/products/en_us/source/" + this.aAltLargeImages[iSelectedIndex-1]; 
			if ( iSelectedIndex && iSelectedIndex != 0 && sLargeImagePath != oLargeImage.src ) {
				oLargeImage.src = sLargeImagePath;
		  }
	
	  } else {
			
			// Update the family thumbnail image
			var sThumbImagePath = "http://ii-prod-rw.marketlive.com/sundance/images/products/en_us/source/" + this.aAltThumbnailImages[iSelectedIndex-1]; 
			if ( iSelectedIndex && iSelectedIndex != 0 && sThumbImagePath != oThumb.src ) {
				oThumb.src = sThumbImagePath;
			}
	}
	
  }
  
  
  // ------------------------- END Sundance custom methods ------------------------- // 
    

  //
  // INITIALIZATION
  //

  // If there are any options, initialize the first menu.
  //
  if (this.aOptionTypes.length > 0) {

    // Get the first option type.
    var oOptionType = this.aOptionTypes[0];

    // Get the select element corresponding to the first option type.
    var oSelect = this.getSelectObj(oOptionType.iPk);

	// (SDC 2010-07-29) Added default chosen value param "0"
    this.loadOptionMenu(oSelect, oOptionType, 0, 0);
	
    // (SDC 2010-06-29) Availability Messaging
    var firstMsg = this.getAvailabilityMessage(this.aOptionSkus[0]);
    var hasMultipleMsg = false;
    for (var i = 1; i < this.aOptionSkus.length; i++) {
    	var oSku = this.aOptionSkus[i];
    	var nextMsg = this.getAvailabilityMessage(oSku);
    	if( firstMsg != nextMsg ){
    		hasMultipleMsg = true;
    		break;
    	}
    }    
    if( !hasMultipleMsg ){
    	// (SDC 2010-06-29) Show first stock messaging if all skus are same
    	myStockMessage = firstMsg;
    } else {
    	// (SDC 2010-05-11) Default stock messaging for multi-skued items
    	myStockMessage = this.sAvailabilityVaries;
    }    
	
  }
  // Else, if showing availability status, update text.
  else {
	
	// (SDC 2009-12-21) Moved Stock Message to .p2p.detail.itemtablerow.tile. Uses oMessagingText1 to populate remote var, myStockMessage
    //var oMessagingText1 = document.getElementById('sdcMessagingText_' + this.iProductPk);
	myStockMessage = this.getAvailabilityMessage(this.findSku([]));
    
	//(SDC 2009-12-21, 2010-04-16 fix) Moved myStockMessage to above line to fix, commented out the conditional below
	/*
	 if (oMessagingText) {
      oMessagingText.innerHTML = this.getAvailabilityMessage(this.findSku([]));
	  oMessagingText.style.display="inline";
    }
	*/
  }
}
