////////////////////////////
// Context for all product details popups on this page.
// NOTE: there is only one of these per page, not one per popup
////////////////////////////

function MProductDetailsContext()
{
    // note that the state is per page, not per details popup
    this._selectedColorDiv = null;
    this._imageExp = /.*\/([a-z0-9]*)/;
    this._productImgUrl = null;
    this._hasClickedColor = false;
    this._restoreProductColor = true;
    // for observing changeColor events
    this.observers = new TxEventObserver();
}

MProductDetailsContext.prototype.updateSizesForColor = function(detailsDiv, availableSizes)
{
    var spans = detailsDiv.getElementsByTagName("span");
    var spansLength = spans.length;
    var sizeIndex = 0;
    for (var index = 0; index < spansLength; index++) {
        var span = spans[index];
        if (span.id == "detailsSize") {
            if (span.origColor == null) {
                span.origColor = span.style.color;
            }
            if (availableSizes == null || availableSizes[sizeIndex] == 1) {
                span.style.color = span.origColor;
            }
            else {
                span.style.color = '#cccccc';
            }
            sizeIndex++;
        }
    }
}

MProductDetailsContext.prototype.swizzleProductImage = function(imageParentDiv, altProductImageUrl)
{
   var productImg = imageParentDiv.productImg;
   if (productImg == null) {
       // If the productImg is not found, nothing to swizzle.
       return;
   }
   if (altProductImageUrl == null || altProductImageUrl == '') {
       var productImgSrc = imageParentDiv.productImgSrc;
       if (productImgSrc !== undefined) {
           productImg.src = productImgSrc;
       }
   }
   else {
       // add param, just for stats gathering
       var separator = altProductImageUrl.indexOf('?') == -1 ? "?" : "&";
       productImg.src = altProductImageUrl + separator + "alt=1";
   }
}

// save the product image information into the fetcher div for later reference
MProductDetailsContext.prototype.initializeProductImg = function(imageParentDiv)
{
    var productImg = imageParentDiv.productImg;
    if (productImg === undefined) {
        // cache the productImg and its src for later restoration
        productImg = findChildTagWithId(imageParentDiv, "IMG", "cellImg");
        // If the cellImg is not found, nothing to initialize.
        if (productImg != null) {
            imageParentDiv.productImg = productImg;
            imageParentDiv.productOriginalImgSrc = productImg.src;
            imageParentDiv.productImgSrc = productImg.src;
        }
    }
    
    return productImg;
}

// change the default image for the product
// the default image is what is shown when the mouse is not over a color swatch
MProductDetailsContext.prototype.setDefaultSource = function(imageParentDiv, defaultSource)
{
    if (defaultSource != null) {
        imageParentDiv.productImgSrc = defaultSource;
    }
    else {
        imageParentDiv.productImgSrc = imageParentDiv.productOriginalImgSrc;
    }
}

/* handleColorMouseOver, handleColorMouseOut, handleColorClick, handleSizeMouseOver, handleSizeMouseOut, handleSizeClick share an interface with registry.js - see ColorTable.java */

MProductDetailsContext.prototype.handleColorMouseOver = function(detailsColorDiv, event, availableSizes, colorIndex)
{
    $(detailsColorDiv).addClassName('detailsColorHilite');
    var detailsDiv = this.getDetailsDiv();
    this.updateSizesForColor(detailsDiv, availableSizes);
    var detailsFetcherDiv = document.detailsContext._currentDetailsFetcherDiv;
    if (detailsFetcherDiv != null && detailsFetcherDiv._colorInfo != null) {
        var colorInfo = detailsFetcherDiv._colorInfo[colorIndex];
        this.swizzleProductImage(detailsFetcherDiv, colorInfo.image);
        if (colorInfo.mimage !== undefined) {
            this.swizzleProductImage(detailsDiv, colorInfo.mimage);
        }
    }
    Event.stop(event);
}

MProductDetailsContext.prototype.handleColorMouseOut = function(detailsColorDiv, event)
{
    $(detailsColorDiv).removeClassName('detailsColorHilite');
    var detailsDiv = this.getDetailsDiv();
    this.updateSizesForColor(detailsDiv, null);
    var detailsFetcherDiv = document.detailsContext._currentDetailsFetcherDiv;
    if (detailsFetcherDiv != null) {
        this.swizzleProductImage(detailsFetcherDiv, null);
        this.swizzleProductImage(detailsDiv, null);
    }
    Event.stop(event);
}

MProductDetailsContext.prototype.handleColorClick = function(detailsColorDiv, event, colorIndex)
{
    // change selection
    if (this._selectedColorDiv != null) {
        $(this._selectedColorDiv).removeClassName('chosenHilite');
    }
    $(detailsColorDiv).addClassName('chosenHilite');
    this._selectedColorDiv = detailsColorDiv;

    // change default image to what is chosen
    var detailsDiv = this.getDetailsDiv();
    var detailsFetcherDiv = document.detailsContext._currentDetailsFetcherDiv;
    this.setDefaultSource(detailsFetcherDiv, detailsFetcherDiv.productImg.src);
    if (detailsDiv.productImg !== undefined) {
        this.setDefaultSource(detailsDiv, detailsDiv.productImg.src);
    }
    
    this._hasClickedColor = true;
    this._productImgUrl = detailsFetcherDiv.productImgSrc;
    Event.stop(event);
}

MProductDetailsContext.prototype.extractImageUrl = function(fullUrl)
{
    if (fullUrl == null) {
        return null;
    }
    var result = fullUrl.match(this._imageExp);
    if (result != null) {
        return result[1];
    }
    else {
        return null;
    }
}

MProductDetailsContext.prototype.setColors = function(colors)
{
    // save the color tokens on the fetcher div for future reference
    var detailsFetcherDiv = document.detailsContext._currentDetailsFetcherDiv;
    detailsFetcherDiv._colorInfo = colors;
    this.setColorSelection(detailsFetcherDiv);
}

// set the color selection style on the color swatch that corresponds to the product image
MProductDetailsContext.prototype.setColorSelection = function(detailsFetcherDiv)
{
    var colorInfo = detailsFetcherDiv._colorInfo;
    if (colorInfo == null || colorInfo.length < 2) {
        // don't show selection if nothing to choose
        return;
    }
    
    var productImgChild = detailsFetcherDiv.productImg;
    if (productImgChild == null) {
        // product cell on spread look image has no productImg, since product cell does not display cellImg img
        return;
    }

    var productImgToken = this.extractImageUrl(productImgChild.src);
    
    var detailsDiv = this.getDetailsDiv();
    var divs = detailsDiv.getElementsByTagName("div");
    var divsLength = divs.length;
    this._selectedColorDiv = null;
    var colorIndex = 0;
    var haveSelected = false;
    for (var divIndex = 0; divIndex < divsLength; divIndex++) {
        var div = divs[divIndex];
        if ($(div).hasClassName('detailsColorHilitable') || $(div).hasClassName('detailsColorText')) {
            if (colorInfo[colorIndex] == null || colorInfo[colorIndex] === undefined || colorInfo[colorIndex].token == "") {
                continue;
            }
            if (productImgToken == colorInfo[colorIndex].token && !haveSelected) {
                this._selectedColorDiv = div;
                $(div).addClassName('chosenHilite');
                haveSelected = true;
            }
            else {
                $(div).removeClassName('chosenHilite');
            }
            colorIndex++;
        }
    }
}

// hook called by details.js when the details dialog appears
MProductDetailsContext.prototype.handleShowDetails = function()
{
    document.colorSizeContext = this;

    var detailsDiv = this.getDetailsDiv();
    var detailsFetcherDiv = document.detailsContext._currentDetailsFetcherDiv;
    this.initializeProductImg(detailsDiv);
    this.initializeProductImg(detailsFetcherDiv);
    this._productImgUrl = detailsFetcherDiv.productImgSrc;
    
    this.setColorSelection(detailsFetcherDiv);
}

//hook called by details.js when the details dialog is hidden (which may happen before it is shown!)
MProductDetailsContext.prototype.handleHideDetails = function()
{
    //trace("productDetails.handleHideDetails");
    var detailsDiv = this.getDetailsDiv();
    var detailsFetcherDiv = document.detailsContext._currentDetailsFetcherDiv;
    var img = null;
    var changeColorLink = null;
    if (detailsFetcherDiv != null) {
        img = detailsFetcherDiv.productImg;
        // if we have a changeColor link then we want to set the color
        changeColorLink = findChildWithId(detailsFetcherDiv, 'changeColorLink');
    }

    // save the color change, if we know a look and favorite
    if (this._selectedColorDiv != null && img != null && changeColorLink != null && this._hasClickedColor) {
        //trace("handleHideDetails saving color");
        var colorToken = this.extractImageUrl(img.src);
        if (changeColorLink != null && changeColorLink.href != null) {
            //trace("sending color change to server");
            var handleAjaxResponse = function(xmlhttp) {
                var responseText = getResponseText(xmlhttp);
                tx_handleUpdatesFromDirectAction(responseText);
            };
            var optionsDict = {
                    asynchronous: true,
                    method: 'get',
                    onSuccess: handleAjaxResponse
            };
            var url = changeColorLink.href;
            url = tx_replaceParam(url, 'colorToken', colorToken);
            new Ajax.Request(url, optionsDict);
        }
        
        // tell any observers that the color has been changed
        this.observers.notify("changeColor", detailsFetcherDiv);
    }

    // set image sources back to the originals (if we aren't editing)
    if (this._restoreProductColor && detailsFetcherDiv != null && detailsFetcherDiv.productOriginalImgSrc != null
            && changeColorLink == null) {
        this.setDefaultSource(detailsFetcherDiv, null);
        this.setDefaultSource(detailsDiv, null);
        this.swizzleProductImage(detailsFetcherDiv, null);
        this.swizzleProductImage(detailsDiv, null);
    }
    
    this._hasClickedColor = false;
}

MProductDetailsContext.prototype.getDetailsDiv = function()
{
    var detailsFetcherDiv = document.detailsContext._currentDetailsFetcherDiv;
    var detailsDiv = document.detailsContext.getDetailsDiv(detailsFetcherDiv);
    return detailsDiv;
}

////////////////////////////
// Sizes Handling
////////////////////////////

MProductDetailsContext.prototype.applyDivMask = function(targetDiv)
{
    var divMask = targetDiv.getAttribute("divMask");
    if (divMask == null) {
        divMask = document.createElement('div');
        targetDiv.setAttribute("divMask", divMask);
        divMask.style.position = 'absolute';
        divMask.style.width = targetDiv.offsetWidth;
        divMask.style.height = targetDiv.offsetHeight;
        divMask.style.top = "0px";
        divMask.style.left = "0px";
        divMask.style.backgroundColor = "white";
        divMask.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=90)";
        divMask.style.zIndex = 100;
        divMask.style.visibility = 'hidden';
        targetDiv.appendChild(divMask);
    }
    divMask.style.visibility = 'visible';
}

MProductDetailsContext.prototype.removeDivMask = function(targetDiv)
{
    var divMask = targetDiv.getAttribute("divMask");
    if (divMask != null) {
        divMask.style.visibility = 'hidden';
    }
}

MProductDetailsContext.prototype.updateColorsForSize = function(detailsDiv, availableColors)
{
    var divs = detailsDiv.getElementsByTagName("div");
    var divsLength = divs.length;
    var colorIndex = 0;
    for (var divIndex = 0; divIndex < divsLength; divIndex++) {
        var div = divs[divIndex];
        if (div.id == "detailsColor") {
            if (availableColors == null || availableColors[colorIndex] == 1) {
                if (isIE7()) {
                    this.removeDivMask(div);
                }
                else {
                    $(div).removeClassName('detailsColorUnavailable');
                }
            }
            else {
                if (isIE7()) {
                    this.applyDivMask(div);
                }
                else {
                    $(div).addClassName('detailsColorUnavailable');
                }
            }
            colorIndex++;
        }
    }
}

MProductDetailsContext.prototype.handleSizeMouseOver = function(detailsSizeSpan, event, availableColors)
{
    if (availableColors != null) {
        $(detailsSizeSpan).addClassName('detailsSizeHilite');
    }
    var detailsDiv = this.getDetailsDiv();
    this.updateColorsForSize(detailsDiv, availableColors);
    Event.stop(event);
}

MProductDetailsContext.prototype.handleSizeMouseOut = function(detailsSizeSpan, event)
{
    $(detailsSizeSpan).removeClassName('detailsSizeHilite');
    var detailsDiv = this.getDetailsDiv();
    this.updateColorsForSize(detailsDiv, null);
    Event.stop(event);
}

MProductDetailsContext.prototype.handleSizeClick = function(detailsSizeSpan, event, sizeName)
{
    Event.stop(event);
}

// handle a mouse click that happens outside the color and size area
MProductDetailsContext.prototype.handleClickOutside = function(event)
{
    if (this._selectedColorDiv != null) {
        $(this._selectedColorDiv).removeClassName('chosenHilite');
        this._selectedColorDiv = null;
    }

    var detailsDiv = this.getDetailsDiv();
    var detailsFetcherDiv = document.detailsContext._currentDetailsFetcherDiv;
    this.setDefaultSource(detailsFetcherDiv, null);
    this.setDefaultSource(detailsDiv, null);
    this.swizzleProductImage(detailsFetcherDiv, null);
    this.swizzleProductImage(detailsDiv, null);
    
    this.setColorSelection(detailsFetcherDiv);
    
    Event.stop(event);
}

function productdetails_openRetailerWindow(url)
{
    var newWindowName = window.name == 'retailerWindow' ? 'retailerWindow1' : 'retailerWindow';
    // Note: we require these window options toforce FireFox2.0 to open in a new window.
    // see: http://www.websitedesignerslist.com/articles/The+Consequences+of+Firefox+2.0+Features+and+Default+Tabs+Settings/
    var newWindow = window.open(url, newWindowName, "menubar=yes,toolbar=yes,location=yes,directories=yes,resizable=yes,scrollbars=yes");
    newWindow.focus();
    return false;
}

MProductDetailsContext.prototype.handleOpenDialog = function(linkElement)
{
    document.detailsContext.clearPendingTimeout();
    document.detailsContext.hideCurrentDetails();
    // if a color has been chosen, fiddle the product image parameter
    var colorToken = this.extractImageUrl(this._productImgUrl);
    var dest = linkElement.href;
    if (colorToken != null) {
        dest = tx_replaceParam(dest, 'objectParams', colorToken);
    }
    // Empty string for pendingOperationUrl means 'do not refresh page -- simply close the dialog'
    return openDialog(linkElement, dest, "");
}

MProductDetailsContext.prototype.handleAddFavorite = function(linkElement)
{
    // if a color has been chosen, fiddle the product image parameter
    var colorToken = this.extractImageUrl(this._productImgUrl);
    if (colorToken != null) {
        var dest = tx_replaceParam(linkElement.href, 'image', colorToken);
        linkElement.href = dest;
    }
}

///////////////////////
// Admin Integration  
///////////////////////

function productdetails_mouseDown(event, productId, adminHost)
{
    if (event.shiftKey) {
        var newWindow = window.open(adminHost + '/Admin/app?service=page&page=QueryProductsPage&uberId=' + productId, 'ShopStyleAdmin');
        newWindow.focus();        
    }
}

//////////////////////////////////////////////////////////////////////////////////////
// Below this point code executes upon parsing.  Above are all functions definitions.
//////////////////////////////////////////////////////////////////////////////////////

// For now, there's a single, global (per page) MProductDetailsContext

document.productDetailsContext = new MProductDetailsContext();
document.colorSizeContext = document.productDetailsContext;

// productDetails needs to watch details context for show/hide
// (if productDetails was a kind of details, rather than independent, this would use methods-calling-super approach)
var showObserver = function() {
    document.productDetailsContext.handleShowDetails();
}
var hideObserver = function() {
    document.productDetailsContext.handleHideDetails();
}
document.detailsContext.observers.addObserver("show", showObserver);
document.detailsContext.observers.addObserver("hide", hideObserver);

