﻿// Javascript for Item Code Selection on product page.
// Used by PFMembers.ascx.

var PFItemNumbers = $A(new Array()); // Array of Item Numbers for choice selects.
var prodGroupId, narrowedList, choiceTypes; // chosen member, current working list of item numbers, choices available
chosenValues = { item_code: '', choiceValue1: '', choiceValue2: '', choiceValue3: '', choiceValue4: '' }; // currently chosen values
var choiceValueFunctions = {
    set: function(index, value) { eval('this.choiceValue' + index.toString() + ' = value'); },
    get: function(index) { return eval('this.choiceValue' + index.toString()); }
}; // getter and setter to make it easier to work with chosenValues in choice select code.
chosenValues = Object.extend(chosenValues, choiceValueFunctions); // add getter and setter to our object.

var choiceSelectName = 'ddl_choice_'; // prefix for choice select inputs.
var linkSwatchesToChoice = { name: '', sort_index: 0 }; // the choice (usually color) that should change views.
var PFSwatches = new Array();
var MainPFImage; // set this in the presentation control to $('colorset');
var chosenSwatchInput; // set this in the presentation control
var chosenItemCodeInput; // set this in the BuyBox control
var chosenProdGroupID; // set this in the BuyBox control
var AddToBasketHookID; // set this in the BuyBox control (registered script block)
var AddToRegistryHookID; // set this in the BuyBox control (registered script block)
var ErrorMessages = {   'SELECT_OPTIONS':'Please select all options above.', 
                        'SPECIAL_HANDLING':'Please fill in all required information above.',
                        'QUANTITY_0':'Please enter a valid quantity above.' };
var throbberTimeout; // used to display throbber if the request is taking too long.
                        
// add to basket or gift registry
function addToBasket(qty, addOrUpdate, chosenHook) {
    // chosen item
    var selected = chosenItem(chosenValues); // should return a single item
    if (!selected) { errorMessage('SELECT_OPTIONS'); return false; }
    if (chosenItemCodeInput) { chosenItemCodeInput.value = selected.item_code; } // update the stuff that was passed into page, from basket or post-add refresh.
    if (!allSpecialHandlingOK()) { errorMessage('SPECIAL_HANDLING'); return false } // hook to check SH values.
    if (qty <= 0) { errorMessage('QUANTITY_0'); return false } // at least 1 in qty field.
    if (__doPostBack) { __doPostBack(chosenHook, addOrUpdate); } // post to basket or gift registry.
    return false;
}

function getAction(form) {
    return form.readAttribute('action') + '?' + form.serialize();
} // find a postback url from a form on the page, with complete querystring. Used for lg views.

// form validation -- make this more complete.
function allSpecialHandlingOK() {
    // define the matching function, within this scope.
    var PromptIsEmpty = function (p) { return ($(p).value == null || $(p).value.strip().empty()); }
    // find all Special Handlings
    var shArray = $$('div[id^="SH"]');
    // find all bad special handlings
    var badSH = shArray.findAll(
        function (i) {
            // find all prompts, required or otherwise, within each special handling
            var notOk, responses; notOk = responses = new Array();
            var reqPrompts = i.select('[id^="SHPrompt_"][required="true"]');
            var allPrompts = i.select('[id^="SHPrompt_"]');

            // find all of those that are filled in
            responses = allPrompts.findAll(function (p) {
                // p.value is not null
                // p.value, trimmed, is not empty string
                return !(PromptIsEmpty(p));
            });
            if (reqPrompts.length > 0) { // if any prompts are required, check for them.
                // find all that are not OK
                notOk = reqPrompts.findAll(function (p) {
                    // check to see that all have values.  If any are blank, return them.
                    return (PromptIsEmpty(p));
                });
            }
            // figure out now if the special handling is okay.  false = ok, true = not ok.
            // is the Special Handling required?
            if (i.getAttribute('required') == "true") {
                // yes -- there must be at least one response and all must be ok
                if (notOk.length > 0) {
                    return true; // not okay -- collect it in the list
                } else {
                    if (responses.length > 0) {
                        return false; // okay.
                    } else { return true; } // we need at least one response for this SH. collect it in the list.
                }
            } else {
                // no -- check if any responses.
                if (responses.length > 0) {
                    // if there are any responses, all must be ok.
                    if (notOk.length > 0) {
                        return true; // not okay -- collect it in the list
                    } else {
                        return false; // okay.
                    }
                } else { return false; } // no responses, but not required. okay.
            }
        });
    if (badSH.length > 0) { return false; } // something wasn't okay.
    return true;
}

// error message
function errorMessage(type) {
    var msg = ErrorMessages[type];
    if (msg) { alert(msg); }
}

// finds selected item from PFItemNumbers
function chosenItem(chosen) {
    if (chosen.item_code != '') { // have an item code, find it in all item numbers and return it.
        if (myItem = PFItemNumbers.find(function(n){ return (n.item_code == this.item_code); }, chosen)) { return myItem; }
    } else if (PFItemNumbers.length == 1) { return PFItemNumbers[0]; // only one item in the pf anyway.
    } 
    if (chosen.choiceValue1 == '') { // have more than one item number, and no choicevalue1. read from form inputs.
        [ '1', '2', '3', '4' ].each(function(n) {
            var ddl, svalue; 
            if (ddl = $(choiceSelectName + n)) {
                svalue = ddl.options[ddl.selectedIndex].value;
                chosen.set(ddl.choice_ValueKey, svalue);
            } 
        });
    }
    narrowedList = narrow(chosen);
    if (narrowedList.length == 1) { return narrowedList[0]; }
    return false;
}

// expects an object, chosen, with properties for each chosen value.  
// Narrows PF Item Numbers down to a working list with the current choices.
function narrow(chosen) {
    var narrowed = PFItemNumbers;
    /* set up our choice value functions, it's easier this way */
    if (!check(chosen.get)) { Object.extend(chosen, choiceValueFunctions); }
    narrowed.each(function(i) { 
        if (!check(i.get)) { Object.extend(i, choiceValueFunctions); }
    });
   // use each input to further narrow the list. 
    [ '1', '2', '3', '4' ].each(function(n) {
        if (!hasChoice(n)) { return; } // if there's no input for this index, skip it.
        var ddl, vkey = n, val;  // drop-down list, choicevaluekey, selected value.
        if (ddl = $(choiceSelectName + n)) {
            /* find drop-down, so we can get the choicevaluekey, which has been added as a property. */
            vkey = ddl.choice_ValueKey;
        }
        if ((val = chosen.get(vkey)) != '') { // use the choice_ValueKey to find the chosen value.
            narrowed = narrowed.findAll(function(i){
                /* vkey should be accessible within this closure */
                return i.get(vkey) == this.get(vkey); 
            }, chosen);  // this == chosen, so see if input's choice value == what's been chosen.
        }
    });
    return narrowed;
}

function hasChoice(sortIndex) {
    if (check(choiceTypes)) {
        return check(choiceTypes.find(function(c) { 
            return (c.sort_index == this); 
        }, sortIndex));
    }
} // is there a choice select input for the sortIndex given?

function fillChoiceSelects(startsFrom) {
    var narrowed, manyChoices;
    manyChoices = hasChoice(3); // if we have more than two choices, use all chosen values. Each select should narrow further.
    
    // figure out a starting point for filling other drop-downs based
    // on choice value already selected.
    if (startsFrom.choice_SortIndex > 0) {
        var selected = { item_code: '', choiceValue1: '', choiceValue2: '', choiceValue3: '', choiceValue4: '' };
        selected = Object.extend(selected, choiceValueFunctions);
        if (manyChoices) { // narrow with selected choices up to startsFrom
            var choiceRange = new ObjectRange(1, startsFrom.choice_SortIndex);
            choiceRange.each(function(n) { // set selected choices for each choice up to startsFrom
                var ddl; if (ddl = $(choiceSelectName + n)) {
                    selected.set(ddl.choice_ValueKey, ddl.options[ddl.selectedIndex].value);
                }
            });
        } else { // more efficient, and 99%+ of pfs have less than 3 choices.
            selected.set(startsFrom.choice_ValueKey, startsFrom.options[startsFrom.selectedIndex].value);
        }
        narrowed = narrow(selected); // figure out the list of members to choose from
    } else { narrowed = PFItemNumbers; } // we're not really sure where we are, fill with all choices.
    
    // fill all four select inputs from the narrowed list of item codes.
    [ '1', '2', '3', '4' ].each(
        function(n) {
            if (manyChoices && n < startsFrom.choice_SortIndex) { return; } // don't backfill if > 2 choices.
            
            var ddl;
            if (ddl = $(choiceSelectName + n)) {  
                var svalue = chosenValues.get(ddl.choice_ValueKey);
                if (ddl == startsFrom) { return; }
                if (ddl.selectedIndex > 0) { 
                    // already selected;
                    svalue = ddl.options[ddl.selectedIndex].value;
                }
                // preserve the first option, which is the prompt text
                var prompt = ddl.options[0];
                ddl.options.length = 0;
                ddl.options[0] = prompt;
                // pull out a list of unique choice values from the narrowed list.
                var prop = 'choiceValue' + n;
                var fillValues = narrowed.pluck(prop).uniq();
                var fillAvail = narrowed.pluck('availMsg');
                var fillWith = (fillValues.length == fillAvail.length)? fillValues.zip(fillAvail): fillValues.zip(fillValues.collect(function(x){return '';}));
                // add an option for each choice value. this == ddl.
                fillWith.each(function(o, index) {
                    if (o[0] == svalue) { 
                        this.options[index + 1] = new Option(o[0].toString() + o[1].toString().stripTags(), o[0], false, true);
                    } else {
                        this.options[index + 1] = new Option(o[0].toString() + o[1].toString().stripTags(), o[0], false, false);
                    }
                }, ddl);                
            }            
        }
    );
}

var choiceSelectHandler = function(e) { // when a user makes a selection from a drop-down.
    var element = Event.element(e);
    if (element.choice_SortIndex < 1) { throw 'Choice ' + element.name + ' has a bad sort index'; return; }
    if (element.choice_ValueKey < 1) { element.choice_ValueKey = element.choice_SortIndex; }
    var sort = element.choice_SortIndex;
    var vkey = element.choice_ValueKey;
    var value = element.options[element.selectedIndex].value;
    //alert([ 'sort:', sort, 'value:', value ].join(' '));

    // tie this to the swatches
    if (linkSwatchesToChoice.sort_index == sort) { 
        set_chosenSwatchColor(value);
        ChangeImage(value); 
    }
    
    chosenValues.set(vkey, value);
    chosenValues.item_code = '';
    //alert(Object.toJSON(chosenValues));
    
    narrowedList = narrow(chosenValues); // narrow the list of item codes
    
    if (narrowedList.length < 1) { // didn't find any. Reset.
        chosenValues = { item_code: '', choiceValue1: '', choiceValue2: '', choiceValue3: '', choiceValue4: '' };
        chosenValues = Object.extend(chosenValues, choiceValueFunctions);
        chosenValues.set(vkey, value);
        //eval('chosenValues.choiceValue' + sort.toString() + '="' + value + '"');
        narrowedList = narrow(chosenValues);
    }
    
    if (narrowedList.length == 1) { 
        oneLeft = narrowedList[0];
        chosenValues.item_code = oneLeft.item_code;
        chosenValues.choiceValue1 = oneLeft.choiceValue1;
        chosenValues.choiceValue2 = oneLeft.choiceValue2;
        chosenValues.choiceValue3 = oneLeft.choiceValue3;
        chosenValues.choiceValue4 = oneLeft.choiceValue4;
    }

    // I don't think this is necessary, but syncs up old page object with new.
    pageState.currentChoiceValues.ChoiceValue1 = chosenValues.choiceValue1;
    pageState.currentChoiceValues.ChoiceValue2 = chosenValues.choiceValue2;
    pageState.currentChoiceValues.ChoiceValue3 = chosenValues.choiceValue3;
    pageState.currentChoiceValues.ChoiceValue4 = chosenValues.choiceValue4;
     
    // fill the rest of the select boxes.
    fillChoiceSelects(element);
    
}
;

function SelectChoice(sortIndex, value, cascade) { // select a value for one of the drop-downs.
    var sel, changed = false;
    if (sel = $(choiceSelectName + sortIndex.toString())) {
        if (sel.options.length <= 1) { changed = true; }
        $A(sel.options).each(
            function(o, i) {
                if (o.value == value) { // try to find the value in the ddl's options.
                    o.selected = true;
                    changed = true;                    
            }});
        if (changed) { // reset the chosen item code.
            chosenValues.item_code = '';
            chosenValues.set(sel.choice_ValueKey, value);
            
            if (cascade) { 
            fillChoiceSelects(sel);
            }
        }
    }
}

/*** Swatches and Image/Movie Display ***/
function ChangeImage(colorValue) { var s;
    if (s = PFSwatches.find(function(i) { return (i.item_color == colorValue); })) {
        HideHeroVideo();
        HideFlashObject();
        HidePlayButton();
        MainPFImage.src = s.src;
    }
}

function ShowFlashObject() {
    var i;
    if (i = $('withFlash')) {
        if (Prototype.Browser.IE6) { i.hide(); }
        else { i.addClassName("showUnderFlash"); i.removeClassName("showOverFlash"); }
    }
}
function HideFlashObject() {
    var i;
    if (i = $('withFlash')) { 
        if (Prototype.Browser.IE6) { i.show(); }
        else { i.addClassName("showOverFlash"); i.removeClassName("showUnderFlash"); }
    }
}
function HidePlayButton() {
    $$('.play_video_icon').invoke('hide');
}

function ShowRichFX() { return ShowFlashObject(); }
function HideRichFX() { return HideFlashObject(); }

function HideHeroVideo() {
    if (typeof(flash_HeroShotVideo) == 'undefined') { return HideFlashObject(); }    
    PauseHeroVideo();
    HidePlayButton();
    return HideFlashObject();
}

function PauseHeroVideo() {
    if (check(flash_HeroShotVideo)) {
        if (!flash_HeroShotVideo.isPaused()) { flash_HeroShotVideo.playPause(); }
    }
}

function ShowHeroVideo(moviename) {
    if (typeof(flash_HeroShotVideo) == 'undefined') { return; }
    flashVars_HeroShotVideo.movieName = moviename;
    if (flash_HeroShotVideo.canPlay()) {
        flash_HeroShotVideo.changeMovie(moviename, flashVars_HeroShotVideo);
    } else {
        var isFlash = flash_HeroShotVideo.changePlayer( 
            flashFile_HeroShotVideo,
            flashVars_HeroShotVideo,
            moviename 
        );
        if (!isFlash) { /* flash is disabled*/
            if (confirm('You need a Flash player to view movies.\nWould you like to download a Flash player from Adobe?')) { window.open('http://www.adobe.com/go/getflashplayer'); }
        }
    }
    HidePlayButton();
    return ShowFlashObject();   
}

function SelectColor(colorValue, eh) { // change the selected color by swatch.
    ChangeImage(colorValue);
    set_chosenSwatchColor(colorValue);
    if (linkSwatchesToChoice.sort_index > 0) {
        SelectChoice(linkSwatchesToChoice.sort_index, colorValue, true);
    }
}

function get_chosenSwatchColor() { 
    if (chosenSwatchInput) { return chosenSwatchInput.value; }
    return '';
}
function set_chosenSwatchColor(value) {
    if (chosenSwatchInput) { chosenSwatchInput.value = value; return chosenSwatchInput.value; }
    return '';
}

function preSelectChoices() {
   
    if (PFItemNumbers.length == 1) { // we only have one item code.
        chosenValues.choiceValue1 = PFItemNumbers[0].choiceValue1;
        chosenValues.choiceValue2 = PFItemNumbers[0].choiceValue2;
        chosenValues.choiceValue3 = PFItemNumbers[0].choiceValue3;
        chosenValues.choiceValue4 = PFItemNumbers[0].choiceValue4;
        chosenValues.item_code = PFItemNumbers[0].item_code;
    }
    
    //if (linkSwatchesToChoice.sort_index > 0 && chosenSwatchValue != "") {
    var chosenSwatch = get_chosenSwatchColor();
    if (chosenSwatch != "") { SelectColor(chosenSwatch); }
    //if (linkSwatchesToChoice.sort_index > 0 && chosenSwatch != "") {
    // we have linked swatches.  Maintain the chosen swatch value if possible.
    //    eval('chosenValues.choiceValue' + linkSwatchesToChoice.sort_index.toString() + '="' + chosenSwatch + '"');
    //}

    [ '1', '2', '3', '4' ].each(function(n) {
        var ddl = $(choiceSelectName + n); //, propName;
        if (ddl) { chosenValue = chosenValues.get(ddl.choice_ValueKey); }
        else { chosenValue = chosenValues.get(n); }
        //chosenValue = eval('chosenValues.choiceValue' + n);
        if ((chosenValue != '') && (ddl)) {
            if (n == linkSwatchesToChoice.sort_index) {
                ChangeImage(chosenValue);
                set_chosenSwatchColor(chosenValue);
            }
            SelectChoice(n, chosenValue, true);
        } else if (ddl && ddl.selectedIndex > 0) { 
            // already selected (possibly from a page reload?);
            chosenValue = ddl.options[ddl.selectedIndex].value;
            if (n == linkSwatchesToChoice.sort_index) {
                ChangeImage(chosenValue);
                set_chosenSwatchColor(chosenValue);
            }
            SelectChoice(n, chosenValue, true);
        }
    });
}

/*** AJAX Member Selection ***/
var memberContainer, memberChoiceSelectCallbackTarget, memberElementName;


function InitMember(prodgroupid) {
    // identify the input associated with the member, add it to the PFMembers collection
    // and set a handler on it for our custom "member:select" event.
    var mo = $('pf_Member_' + prodgroupid.toString());
    mo.prodgroupID = prodgroupid;
    PFMembers.push(mo);
    Event.observe(mo, "member:select", SelectMember.bindAsEventListener(mo));
}

function SelectMember(selectedPGID) {
    if (selectedPGID > 0) {
        // if this has been called externally, check for a member element and fire the custom selection event on it.
        var sM;
        if (check(sM = PFMembers.find(function(member) { return (member.prodgroupID == selectedPGID); }))) {
            sM.fire("member:select"); 
            return;
        } // if there's no member element available, fall through.
    } else { 
        // format the members to UNSELECTED.
        PFMembers.each(function(element) { element.addClassName('unselected'); element.removeClassName('selected'); });

        // if this has been called as an event handler on a member element, fetch the prodgroupid and set it to SELECTED.
        selectedPGID = this.prodgroupID;
        this.addClassName('selected');
        this.removeClassName('unselected');
    }
    // if we're not actually changing the member, don't re-fetch.
    if (pageState.prodGroupID == selectedPGID) { return; }
    // set a throbber to display a message after 1/2 second.
    throbberTimeout = window.setTimeout(function(){memberContainer.update('<span class="throbber">Please wait while we load further options.</span>');}, 500);
    // fetch the member info AJAXily.
    pageState.prodGroupID = selectedPGID;
    if (chosenProdGroupID) { chosenProdGroupID.value = selectedPGID; }
    callMeBack(
        Object.toJSON({ "pf_id": pageState.pfid, "prodgroupid": pageState.prodGroupID }), 
        memberChoiceSelectCallbackTarget, 
        function(retValue) { 
            var status, content, ret;
            ret = retValue.split('|');
            status = ret[0]; content = ret[1];
            window.clearTimeout(throbberTimeout);
            if (check(content)) {
                memberContainer.update(content); }
            else { 
                status = retValue.substring(0, 1);
                content = retValue.substring(1, retValue.length)
                if (status == "e") { //error
                    content = "<span class='error'>" + content + "</span>";
                    }
                memberContainer.update(content); }
        },
        function(errorObj) { window.clearTimeout(throbberTimeout); memberContainer.update("<span class='error'>We're sorry, an error has occurred on our server.</span>"); } // this should change
    );
       
}

/* Buy Another */
Event.observe(document, "basket_add:choose", function(e) { e.stop(); if (hideBasketStatus) { hideBasketStatus(); } if (buyAnother) { buyAnother(); }});
//Event.observe(document, "gr_add:choose", function(e) { e.stop(); if (clearGiftRegURL) { clearGiftRegURL(); } if (buyAnother) { buyAnother(); } if (hideBasketStatus) { hideBasketStatus(); }});

/*** Page State -- from ProductPageScripts.js ***/

//Represents the state of common page level variables
function PageState(){
    this.__type = 'Orvis.ProductPage.ProductPageState';
    this.pfid = '';
    this.prodGroupID = '';
    this.imagePath = '';
    this.currentChoiceValues = null; 
} // add item_code property to this class. Then we can use it for chosenValues.

//Represents the current choice value selections
function CurrentChoiceValues(){
    this.__type = 'Orvis.ProductPage.CurrentChoiceValues';
    this.ChoiceValue1 = '';
    this.ChoiceValue2 = '';
    this.ChoiceValue3 = '';
    this.ChoiceValue4 = '';
}

var pageState;

