﻿//------------------------------------DimensionSelector----------------------------------------------------//
//Wraps up functionality of a single dimension selector.
//Notes:
//  This code relies on certain HTML being in place, so be careful when modifying dimension selector HTML.
//  Anything that starts with JQ is a jQuery object.
//  Should be able to handle an empty jqSelector.
function DimensionSelector(jqSelector, selectedStyleID, styleArray, selectedDimensionID) {
    this.Selector = jqSelector; 										//JQuery selector that contains the dimension selector
    this.SelectedDimensionID = 0; 										//Current selected dimension ID (user has clicked)
    this.ActiveDimensionID = 0; 										//Current active dimension ID (user is hovering or clicked)
    this.ActiveText = ''; 												//Current text displayed to user (user is hovering or clicked)
    this.SelectedText = ''; 											//Current selected dimension text (user has clicked)
    this.JQSelectedObject = null; 										//Current selected JQuery object (user has clicked)
    this.JQActiveObject = null; 										//Current active Jquery object (user is hovering or clicked)
    this.JQTextContainer = this.Selector.find('input.dimTextDisplay:first'); //A JQuery object that contains the selected text
    this.JQDimensions = this.Selector.find('label.pdp-options'); 		//A JQuery object that contains the list of dimension UI objects
    this.JQIDContainer = this.Selector.find('input.dimID:first'); 		//A JQuery object that contains the selected ID
    this.DimensionTypeName = this.Selector.find('.dimType:first').val();//Name of the dimension type
    var self = this; 													//Reference to self for scoping
    this.StyleArray = styleArray;
    if (this.Selector.length == 0)
        return;

    
    var inputName = this.JQDimensions.find('input:radio:first').attr('name');
    if (selectedDimensionID != undefined && selectedDimensionID != null && parseInt(selectedDimensionID) > 0)
        this.JQIDContainer.attr('value', selectedDimensionID.toString());
    
    //These radio buttons will only be used when JS is not
    this.JQDimensions.find('input:radio').remove();
    //if the ID has already been set, update the dimensions accordingly.
    if (this.JQIDContainer.val() != '') {
        this.SelectDimension(this.JQIDContainer.siblings('label[value="' + this.JQIDContainer.val() + '"]'));
        this.DisplayValidDimensions(selectedStyleID, parseInt(this.JQIDContainer.val()));
    }

    //Create event handlers for the dimension UI objects - mouseenter, mouseleave, and click
    this.JQDimensions
		.bind('mouseenter', function() {
		    self.HoverIn($(this));
		    self.OnHoverIn(self);
		})
		.bind('mouseleave', function() {
		    self.HoverOut($(this));
		    self.OnHoverOut(self);
		})
		.click(function() {
		    self.SelectDimension($(this));
		    self.OnSelected(self);
		    return false;
		});
}

//Public events
DimensionSelector.prototype.OnHoverIn = function(ds) { }
DimensionSelector.prototype.OnHoverOut = function(ds) { }
DimensionSelector.prototype.OnSelected = function(ds) { }

//Public Methods
DimensionSelector.prototype.IsSelectedValid = function() {
    //if this is not a valid Selector, return true;
    return this.Selector.length == 0 ||(this.JQSelectedObject != null && this.JQSelectedObject.hasClass('valid'));
}

DimensionSelector.prototype.IsActiveValid = function() {
    return this.Selector.length == 0 || (this.JQActiveObject == null || this.JQActiveObject.hasClass('valid'));
}

DimensionSelector.prototype.IsSelectedOutOfStock = function() {
    return this.JQSelectedObject != null && this.JQSelectedObject.hasClass('outOfStock');
}

DimensionSelector.prototype.IsActiveOutOfStock = function() {
    return this.JQActiveObject != null && this.JQActiveObject.hasClass('outOfStock');
}

DimensionSelector.prototype.HoverIn = function(jqObj){
    this.JQActiveObject = jqObj;
    this.ActiveDimensionID = parseInt(this.JQActiveObject.attr('value'));
    this.ActiveText = this.JQActiveObject.attr('title');
    this.JQActiveObject.siblings().removeClass('selected');
    this.JQActiveObject.addClass('selected');
    this.JQTextContainer.val(this.JQActiveObject.attr('title'));
}

DimensionSelector.prototype.HoverOut = function(jqObj){
    if (this.SelectedDimensionID != this.ActiveDimensionID)
        this.JQActiveObject.removeClass('selected');

    if (this.JQSelectedObject != null)
        this.JQSelectedObject.addClass('selected');
    this.ActiveDimensionID = this.SelectedDimensionID;
    this.ActiveText = this.SelectedText;
    this.JQActiveObject = this.JQSelectedObject;
    this.JQTextContainer.val(this.SelectedText);
}

//Called when a user clicks on a dimension, or when the object first loads and a dimension is already selected
DimensionSelector.prototype.SelectDimension = function(jqObj) {
    if (jqObj.length == 0)
        return;
    this.UnselectDimension();
    this.JQActiveObject = this.JQSelectedObject = jqObj;
    this.SelectedDimensionID = this.ActiveDimensionID = parseInt(this.JQSelectedObject.attr('value'));
    this.SelectedText = this.ActiveText = this.JQSelectedObject.attr('title');
    this.JQIDContainer.val(this.SelectedDimensionID);
    this.JQTextContainer.val(this.JQSelectedObject.attr('title'));
    //this.JQSelectedObject.siblings().removeClass('selected');
    this.JQSelectedObject.addClass('selected');
}

//Unselects the currently selected dimension
DimensionSelector.prototype.UnselectDimension = function() {
    this.JQActiveObject = this.JQSelectedObject = null;
    this.SelectedDimensionID = this.ActiveDimensionID = 0;
    this.SelectedText = this.ActiveText = '';
    this.JQIDContainer.val('');
    this.JQTextContainer.val('');
    this.JQDimensions.removeClass('selected');
}

//This will select the valid dimension if there is only one valid one available
DimensionSelector.prototype.SelectSingleValid = function() {
    if (this.JQDimensions.not('.invalid').length == 1)
        this.SelectDimension(this.JQDimensions.not('.invalid'));
}

//Updates the UI to show which dimensions are valid for the selected style/dimension
DimensionSelector.prototype.DisplayValidDimensions = function(styleID, otherDimensionID) {
    if (this.Selector.length == 0)
        return;
        
    var relatedVariations = StyleSelector.FindVariations(this.StyleArray, styleID, otherDimensionID);
    this.JQDimensions.each(function() {
        var thisID = parseInt($(this).attr('value'));
        var variation = null;
        var inStock = false;
        for (var v in relatedVariations) {
            if (relatedVariations[v].Dimension1ID == thisID) {
                variation = relatedVariations[v];
                if (variation.IsInStock)
                    inStock = true;
            }
            else if (relatedVariations[v].Dimension2ID == thisID) {
                variation = relatedVariations[v];
                if (variation.IsInStock)
                    inStock = true;
            }
        }

        if (variation == null)
            $(this).removeClass('valid').removeClass('outOfStock').addClass('invalid');
        else if (!inStock)
            $(this).removeClass('invalid').removeClass('valid').addClass('outOfStock');
        else
            $(this).removeClass('invalid').removeClass('outOfStock').addClass('valid');

    });
    if (this.SelectedDimensionID == 0) {
        if (this.JQDimensions.filter('.valid').length == 1)
            this.HoverIn(this.JQDimensions.filter('.valid:first'));
        else
            this.HoverOut(this.JQDimensions.filter('.selected'));
    }
}

//If the currently selected dimension is invalid, unselect it.
//This requires that DisplayValidDimensions has already been called.
DimensionSelector.prototype.ValidateSelected = function() {
    if (this.JQSelectedObject === null)
        return;
    if (this.JQSelectedObject.hasClass('invalid'))
        this.UnselectDimension();
}

//------------------------------------End DimensionSelector-------------------------------------------------//


//Represents a style (or color) selector. 
//------------------------------------------StyleSelector---------------------------------------------------//
function StyleSelector(jqSelector, styleArray, selectedStyle) {
    this.SelectedStyle = selectedStyle;                 //Selected style (user has clicked, or selected by default.)
    this.ActiveStyle = selectedStyle;                   //Active style (user is hovering or clicked)
    this.JQStyles = jqSelector.find('a');               //JQuery selector for clickable units.
    this.Selector = jqSelector;                         //JQuery selector for entire style selector
    this.JQIDContainer = $('#styleId');                 //JQuery selector for the element containing the selected style ID
    var self = this;                                    //pointer to this
    this.StyleArray = styleArray;

    if (this.JQIDContainer.val() != selectedStyle.Key)
        this.SelectStyle(this.JQStyles.filter("[value='" + this.JQIDContainer.val() + "']"));
        
    //JQuery event handlers
    this.JQStyles
		.bind('mouseenter', function() {
            self.StyleHoverIn($(this));
            self.OnHoverIn(self);
		})
		.bind('mouseleave', function() {
		    self.StyleHoverOut($(this));
		    self.OnHoverOut(self);
		})
		.click(function() {
		    self.SelectStyle($(this));
		    self.OnSelected(self);
		    return false;
		});
}

StyleSelector.prototype.FindJQStyleObject = function(styleID) {
    return this.Selector.find("a[value='" + styleID.toString() + "']");
}

//Handler for mouse-over on a style
StyleSelector.prototype.StyleHoverIn = function(jqObj) {
    jqObj.addClass('selected');
    var ActiveStyleID = parseInt(jqObj.attr('value'));
    this.ActiveStyle = StyleSelector.FindStyle(this.StyleArray, ActiveStyleID);
    if (this.SelectedStyle != null) {
        $('#mainProductImage').attr('src', this.ActiveStyle.MainImage);
        $('#selectedColor').val(this.ActiveStyle.SpecificColorName);
        $('#productDetailColor').text(this.ActiveStyle.SpecificColorName);
        $('#productDetailStockNumber').text(this.ActiveStyle.StockNumber);
    }
}

//Handler for mouse-out on a style
StyleSelector.prototype.StyleHoverOut = function(jqObj) {
    jqObj.removeClass('selected');
    this.FindJQStyleObject(this.SelectedStyle.Key).addClass('selected');
    this.ActiveStyle = this.SelectedStyle;
    $('#mainProductImage').attr('src', this.SelectedStyle.MainImage);
    $('#selectedColor').val(this.SelectedStyle.SpecificColorName);
    $('#productDetailColor').text(this.SelectedStyle.SpecificColorName);
    $('#productDetailStockNumber').text(this.SelectedStyle.StockNumber);
    
}

//Handler for selecting a style (user clicked)
StyleSelector.prototype.SelectStyle = function(jqObj) {
    this.StyleHoverIn(jqObj);
    jqObj.removeClass('invalid');
    this.SelectedStyle = this.ActiveStyle;
    $('#mainzoom').attr('href', this.SelectedStyle.ZoomImage);
    this.JQStyles.removeClass('selected');
    jqObj.addClass('selected');
    this.JQIDContainer.val(this.SelectedStyle.Key);
    //if s has already been created, just call the darn thing,
    //otherwise wait til the page loads, then do it
    try { this.SelectedStyle.DoAnalytics(); }
    catch (e) { var self = this; $(function() { self.SelectedStyle.DoAnalytics(); }); }
}

//Updates the UI to show which styles are valid for the selected dimensions. Neither
//dimension is required. Please pass 0 for unselected dimensions instead of null.
StyleSelector.prototype.DisplayValidStyles = function(dimension1ID, dimension2ID) {
    if (dimension1ID == 0 && dimension2ID == 0)
        return;
    var relatedVariations = new Array();
    var self = this;

    this.JQStyles.each(function() {
        var thisID = parseInt($(this).attr('value'));
        var relatedVariations = new Array();
        var variation = null;
        var inStock = false;

        if (dimension2ID == 0)
            relatedVariations = StyleSelector.FindVariations(self.StyleArray, thisID, dimension1ID, true);
        else if (dimension1ID == 0)
            relatedVariations = StyleSelector.FindVariations(self.StyleArray, thisID, dimension2ID, true);
        else {
            variation = StyleSelector.FindVariation(self.StyleArray, thisID, dimension1ID, dimension2ID);
            if (variation != null)
                inStock = variation.IsInStock;
        }
        for (var v in relatedVariations) {
            if ((relatedVariations[v].Dimension1ID == dimension1ID && dimension1ID > 0) || (relatedVariations[v].Dimension2ID == dimension2ID && dimension2ID > 0)) {
                variation = relatedVariations[v];
                if (relatedVariations[v].IsInStock)
                    inStock = true;
            }
        }

        if (variation == null)
            $(this).removeClass('valid').removeClass('outOfStock').addClass('invalid');
        else if (!inStock)
            $(this).removeClass('invalid').removeClass('valid').addClass('outOfStock');
        else
            $(this).removeClass('invalid').removeClass('outOfStock').addClass('valid');
    });

}
StyleSelector.prototype.FindAndSelectStyle = function(dimension1ID, dimension2ID) {
    if (dimension1ID == 0 || dimension2ID == 0)
        return false;
    var self = this;
    var gotone = false;
    var secondBest = null;
    this.JQStyles.each(function() {
        if (!gotone) {
            var thisID = parseInt($(this).attr('value'));
            var variation = StyleSelector.FindVariation(self.StyleArray, thisID, dimension1ID, dimension2ID);

            //if the variation is out of stock keep looking.
            //However, if the best thing we can find is out of stock, then select it.
            if (variation != null) {
                if (variation.IsInStock) {
                    self.SelectStyle($(this));
                    gotone = true;
                }
                else if(secondBest == null) {
                    secondBest = $(this);
                }
            }
        }
    });
    if (!gotone && secondBest != null) {
        self.SelectStyle(secondBest);
        gotone = true;
    }
    if (gotone)
        self.OnSelected(self);
    return gotone;
}
//Public events.
StyleSelector.prototype.OnHoverIn = function(ss) { }
StyleSelector.prototype.OnHoverOut = function(ss) { }
StyleSelector.prototype.OnHoverSelected = function(ss) { }

//Static methods

//Finds all style variations for a dimension and style
//If dimID is null or 0, all variations of the style will be returned.
StyleSelector.FindVariations = function(StylesArray, styleID, dimID) {
    var rval = new Array();
    for (var s in StylesArray) {
        if (StylesArray[s].Key == styleID) {
            for (var v in StylesArray[s].Variations) {
                if ((dimID == 0 || dimID == null) || (StylesArray[s].Variations[v].Dimension1ID == dimID || StylesArray[s].Variations[v].Dimension2ID == dimID)) {
                    rval.push(StylesArray[s].Variations[v]);
                }
            }
        }
    }
    return rval;
}

//Finds a style variation for 2 dimensions and style
//dim1ID and dim2ID are both required.
StyleSelector.FindVariation = function(StylesArray, styleID, dim1Id, dim2Id) {
    for (var s in StylesArray) {
        if (StylesArray[s].Key == styleID) {
            for (var v in StylesArray[s].Variations) {
                if ((StylesArray[s].Variations[v].Dimension1ID == dim1Id || StylesArray[s].Variations[v].Dimension1ID == dim2Id) && (StylesArray[s].Variations[v].Dimension2ID == dim1Id || StylesArray[s].Variations[v].Dimension2ID == dim2Id)) {
                    return StylesArray[s].Variations[v];
                    break;
                }
            }
        }
    }
    return null;
}

//Finds a style in the array.
StyleSelector.FindStyle = function(StylesArray, styleID) {
    for (var s in StylesArray) {
        if (StylesArray[s].Key == styleID) 
            return StylesArray[s];
    }
    return null;
}
//------------------------------------------End StyleSelector-----------------------------------------------//

