﻿
var currentUIRenderRequests = 0;
var cartLoadComplete = false;
var printSizes = null;
var cdCartItem = null;
var cdPrice = 0;

function onGotCartItemCounts()
{
    showLoadingPopup();

    printSizes = shoppingCart.getPrintSizesInfo();

    if (shoppingCart.getNumProductsInCartByType('Prints') > 0)
    {
        document.getElementById('PhotoCDSection').style.display = 'block';
        RenderQuickSetHTML(printSizes);
    }
}
function onRenderCartItemBatch(sender, batch)
{
    var sb = new PhotoSite.Framework.StringBuilder();


    for (var i = 0; i < batch.length; i++)
    {
        
        var pt = batch[i].ProductType;

        if (pt == 'Prints')
        {
            sb.append(RenderPrintItemHTML(batch[i]));
        }
        else if (pt != 'CD')
        {
            sb.append(RenderGiftItemHTML(batch[i]));
        }
        else
        {
            cdCartItem = batch[i];
            cdPrice = cdCartItem.Price;
            document.getElementById('OrderPhotoCD').checked = true;
            document.getElementById('photoCDPrice').innerHTML = cdPrice.toFixed(2);
        }
    }

    currentUIRenderRequests++;

    setTimeout(function(builder)
    {
        return function()
        {
            appendBuilderToDocument(builder);
        };
    } (sb), 0);
}

function appendBuilderToDocument(builder)
{
    var content = document.createElement('div');
    content.innerHTML = builder.toString();
    cartItemsDiv.appendChild(content);
    currentUIRenderRequests--;

    if (cartLoadComplete && currentUIRenderRequests == 0)
    {
        hideLoadingPopup();
    }
}

function RenderQuickSetHTML(printSizes)
{
    var sb = new PhotoSite.Framework.StringBuilder();

    sb.append('<div class="quick_order_fields"><div style="width: 210px;" class="dgrey"><strong><div style="width: 90px; text-align: center;" class="left">',
                  SR.Quantity,
              '</div><div style="width: 60px;" class="left">',
                  SR.Options,
              '</div><div style="width: 60px; text-align: right;" class="left">',
                  SR.Borders,
              '</div></strong></div></div>');

    for (var i = 0; i < printSizes.length; i++)
    {
        var printSize = printSizes[i];

        if (i === 5)
        {
            sb.append('<div id="quickset_enlargements" style="display:none">');
        }

        sb.append('<div class="quick_order_fields">');

        // Name
        sb.append('<div class="quick_order_size">', printSize.Name, '</div>');

        // Quantity
        sb.append('<div class="quick_order_qty">',
                      '<input id="qdd_', printSizes[i].EncRetailerProductID, '" type="text" onkeyup="quickSetQuantityChanged(this, \'', printSizes[i].EncRetailerProductID, '\');" value="0" maxlength="3" size="3"/>',
                  '</div>');

        // Options
        sb.append('<div class="quick_order_options">');

        // Surface
        sb.append('<span><select id="surface_', printSize.EncRetailerProductID, '" onchange="quickSetSurfaceChanged(this, \'', printSize.EncRetailerProductID, '\')">');

        for (var j = 0; j < printSize.SurfaceOption.Values.length; j++)
        {
            var value = printSize.SurfaceOption.Values[j];

            sb.append('<option value="', value.EncOptionValueID, '"');

            if (value.EncOptionValueID == printSize.SurfaceOption.SelectedOptionValueID)
            {
                sb.append(' selected="selected"');
            }

            sb.append('>', value.Name, '</option>');
        }

        sb.append('</select></span>');

        // Border
        if (printSize.BorderOption)
        {
            var selectedValue = null;

            for (var j = 0; j < printSize.BorderOption.Values.length; j++)
            {
                var value = printSize.BorderOption.Values[j];

                if (value.EncOptionValueID == printSize.BorderOption.SelectedOptionValueID)
                {
                    selectedValue = value;
                    break;
                }
            }

            sb.append('<img id="quickset_border_', printSize.EncRetailerProductID, '" onclick="quickSetBorderChanged(this, \'', printSize.EncRetailerProductID, '\')" src="../images/img_checkbox_');

            if (value.Name == 'True')
            {
                sb.append('on');
            }
            else
            {
                sb.append('off');
            }

            sb.append('.gif" />');
        }

        sb.append('</div>');

        sb.append('</div>');
    }

    sb.append('</div>');

    document.getElementById('quick_set_controls').innerHTML = sb.toString();
    document.getElementById('QuickOrderSection').style.display = 'block';
    
    //hide the alternate 90 day warning because there is one in the quick order section already
    if($get('alt90DayMsg') != null)
        $get('alt90DayMsg').style.display = 'none';
}

function RenderPrintItemHTML(cartItem)
{
    var groupID = cartItem.GroupID;
    var localPrintSizes = printSizes;
    var localSubItems = cartItem.SubItems;

    var sb = new PhotoSite.Framework.StringBuilder();

    sb.append('<div class="order_item" id="container_', groupID, '">');

    // Thumbnail div
    sb.append('<div class="order_thumb">',
                  '<img id="img_', groupID, '" src="', cartItem.ThumbUrl, '" onclick="showCropper(\'', groupID, '\'); return false;"><br />',
                  '<p><a href="#" onclick="showCropper(\'', groupID, '\'); return false;">', SR.ChangeCrop, '</a></p>',
              '</div>');

    // Information div
    sb.append('<div class="order_desc">');

    // name...
    sb.append('<p><strong class="dgrey">', cartItem.Name, '</strong></p>');

    var price = shoppingCart.calculatePrintPrice(cartItem).toFixed(2);

    // price...
    sb.append('<p>', SR.PriceCartItem, ': $<span id="price_', groupID, '">', price, '</span>', '</p>');

    // printing on back...
    sb.append('<p>',
                  SR.PrintingOnBack, ': <input type="text" maxlength="', backPrintingMaxChars, '" id="back_printing_', groupID, '" value="', cartItem.BackPrinting.Text, '" onkeydown="PrintingOnBackChanged(this, \'', groupID, '\'); return true;" >',
              '</p>');

    sb.append('<p>', SR.Max, ' ', backPrintingMaxChars, ' ', SR.CharactersRemaining,
                  ' <span id="backprinting_chars_', groupID, '">',
                  backPrintingMaxChars - cartItem.BackPrinting.Text.length,
                  '</span>',
              '</p>');

    // photo preview button...
    sb.append('<p>',
                  '<a href="#" onclick="onPhotoPreviewClick(\'', groupID, '\'); return false;"><strong>',
                      SR.PhotoPreview,
                  '</strong></a> &nbsp; ',
                  '<a href="#" onclick="onCartItemRemoveClick(\'', groupID, '\'); return false;"><strong>',
                      SR.RemoveCartItem,
                  '</strong></a>',
              '</p>');

    // Information div end
    sb.append('</div>');

    // Quantity / Prices div
    sb.append('<div class="order_qty">');

    // Header
    sb.append('<div class="quick_order_fields">',
                  '<div style="width: 240px;" class="dgrey"><strong><div class="left" style="width: 90px; text-align: center;">',
                      SR.Quantity,
                  '</div><div class="left" style="width: 90px;">',
                      SR.Options,
                  '</div><div class="left" style="width: 60px; text-align: right;">',
                      SR.Borders,
                  '</div></strong></div>',
              '</div>');

    var subItemHTML = RenderPrintSubItemHTML(0, 5, groupID, localSubItems, localPrintSizes);
    sb.append(subItemHTML);

    sb.append('<div id="enlargements_container_', groupID, '"></div>');

    sb.append('<div class="quick_order_btm">',
                  '<a href="#" onclick="onExpandEnlargementsClick(\'', groupID, '\'); return false;"><strong id="enlargements_button_', groupID, '">',
                      SR.OrderEnlargementPrints,
                  '</strong></a>',
              '</div>');

    sb.append('</div>', '</div>');

    return sb.toString();
}

function RenderPrintSubItemHTML(startIndex, endIndex, groupID, localSubItems, localPrintSizes)
{
    var sb = new PhotoSite.Framework.StringBuilder();
    var useDivForInput = (Sys.Browser.agent == Sys.Browser.Firefox || Sys.Browser.agent == Sys.Browser.InternetExplorer);

    for (var i = startIndex; i < endIndex; i++)
    {
        var si = localSubItems[i];
        var siRPID = si.EncRetailerProductID;
        var groupID_siRPID = groupID + '_' + siRPID;

        sb.append('<div class="quick_order_fields">');

        sb.append('<div class="quick_order_size">',
                      localPrintSizes[i].Name,
                  '</div>');

        sb.append('<div class="quick_order_qty">');

        if (useDivForInput == false)
        {
            sb.append('<input style="border:1px solid gray" maxlength="3" size="2" id="qty_');
            sb.append(groupID);
            sb.append('_');
            sb.append(siRPID);
            sb.append('" type="text" value="');
            sb.append(si.Quantity);
            sb.append('" onkeyup="PrintQuantityChanged(this, \'');
            sb.append(groupID);
            sb.append('\', ');
            sb.append(i);
            sb.append(');">');
        }
        else
        {

            sb.append('<div id="qty_div_', groupID, '_', i, '" onmousedown="printQuantityDivClicked(this, \'', groupID, '\', \'', i, '\', true)">',
                         si.Quantity,
                      '</div>');
        }

        sb.append('</div>');

        sb.append('<div class="quick_order_options">');

        // Surface and warning
        sb.append('<div style="width: 120px;height:15px;" class="left">');

        // Surface
        sb.append('<div class="left" style="padding-right:7px" id="surface_', groupID_siRPID, '">',
                     si.PrintSurface.Name,
                  '</div>');

        // Resolution Warning
        sb.append('<div style="margin-right: 3px;');

        if (si.Quantity == 0 || si.WarnRes == false)
        {
            sb.append('display:none;');
        }

        sb.append('" class="left" id="warnres_',
                      groupID_siRPID,
                  '"><img src="../images/icon_warning.gif" border="0"></div>');

        // Crop Warning
        if (si.WarnCrop)
        {
            sb.append('<div style="cursor:pointer;');

            if (si.Quantity == 0)
            {
                sb.append('display:none;');
            }

            sb.append('" onclick="showCropper(\'', groupID, '\',\'', siRPID, '\')" class="left" id="warncrop_', groupID_siRPID, '"><img src="../images/crop_icon', SR.LanguageSuffix, '.jpg" border="0"></div>');
        }

        sb.append('</div>');    // surface and warning

        if (si.PrintBorder && si.PrintBorder.Name.length > 0)
        {
            sb.append('<div class="left"><img id="border_',
                          groupID_siRPID,
                      '" onclick="SubItemBorderChanged(this, \'',
                          groupID,
                      '\', \'',
                          siRPID,
                      '\');" src="../images/img_checkbox_');

            if (si.PrintBorder.Name == 'True')
            {
                sb.append('on');
            }
            else
            {
                sb.append('off');
            }

            sb.append('.gif" /></div>');
        }

        sb.append('</div>');    // quick_order_options

        sb.append('</div>');
    }

    return sb.toString();
}

function GetGiftURL(productType)
{
   
    if (productType == 'EnhancementPrints')
    {
        return '../album/enhance_landing.aspx';
    }
    else if (productType == 'CustomFrame')
    {
        return '../album/framing_landing.aspx';
    }
    else if (productType != 'Calendars' && productType != 'PhotoCalendars' && productType != 'PhotoBooks' &&
             productType != 'TreasureknitGenericProduct' && productType !='BusinessPrintingExternal' && productType != 'BusinessPrints' && 
             productType != 'BusinessPrinting')
    {
        return '../album/gifts_select_options.aspx';// temporary for hot fix of collage null xml
    }
    else
    {
        return '';
    }
}

function RenderGiftItemHTML(cartItem)
{
    var groupID = cartItem.GroupID;
    var sb = new PhotoSite.Framework.StringBuilder();


    if(cartItem.ProductType == 'TreasureknitGenericProduct')
    {
        cartItem.ThumbUrl = '../images/cart/tk-cart-icon.png';
    }

   
    sb.append('<div id="container_');
    sb.append(groupID);
    sb.append('" class="order_item">');

    sb.append('<div class="order_thumb">');
    sb.append('<img border="0" style="max-width: 106px; max-height: 112px;" src="');
    sb.append(cartItem.ThumbUrl);
    sb.append('" alt="');
    sb.append(cartItem.ProductType);
    sb.append('">');
    sb.append('</div>');

    sb.append('<div class="order_desc">');
    sb.append('<p><strong class="dgrey">');
    sb.append(cartItem.Name);
    sb.append('</strong>');

    if (cartItem.Description)
    {
        sb.append('<br/>', cartItem.Description);
    }
    
    sb.append('</p><p>');
    sb.append(SR.PriceCartItem);
    sb.append(': $<span id="price_');
    sb.append(groupID);
    sb.append('">');
    sb.append(shoppingCart.calculateCartItemPrice(cartItem).toFixed(2));
    sb.append('</span></p><p>');

    //Added to show Attributes
    if (cartItem.Attributes) {
        for (var m = 0; m < cartItem.Attributes.length; m++) {
            sb.append(cartItem.Attributes[m].Name + ' : ' + cartItem.Attributes[m].Value + '<br />');
        }
        sb.append('<p>');
    }

    if (cartItem.ProductType != 'BusinessPrinting' && cartItem.PackageOptionValue)
    {
        sb.append(SR.PackOf, ': ', cartItem.PackageOptionValue.Name);
        sb.append('</p><p>');
    }

    var url = '';
    

   if (cartItem.ProductType == "GreetingCards" || cartItem.ProductType == "BorderedGreetingCards") {
            sb.append("<a href='#' ");
            sb.append("onclick=showPreview('");
            sb.append(cartItem.EncID);
            sb.append("')><strong>");
            sb.append(SR.Preview);
            sb.append('</strong></a> &nbsp; ');
   }

    
    
    if (url != '')
    {
        sb.append('<a href="', url, '?q=', cartItem.EncID, '&origin=cart"><strong>', SR.Preview, '</strong></a> &nbsp; ');
    }
    
    
    sb.append('<a href="#" onclick="onCartItemRemoveClick(\'');
    sb.append(groupID);
    sb.append('\'); return false;"><strong>');
    sb.append(SR.RemoveCartItem);
    sb.append('</strong></a></p>');

    if (cartItem.BackToAlbum)
    {
        sb.append('<div class="left" style="width:22px; padding-top:8px">');

        sb.append('<img onclick="backToAlbumChanged(this, \'');
        sb.append(groupID);
        sb.append('\');" src="../images/img_checkbox_');
        sb.append(cartItem.BackToAlbum.Name === 'Yes' ? 'on' : 'off');
        sb.append('.gif">');

        sb.append('</div>');
        sb.append('<div class="left" style="width:180px; padding-top:5px">');
        sb.append(SR.SaveACopyOfThisPhotoToEnhancedImagesAlbum);
        sb.append('<a href="#" onclick="openHelpPopup(' + backToAlbumHelpURL + ');">' + SR.MoreInfo + '</a>');
        sb.append('</div>');
    }

    sb.append('</div>');

    sb.append('<div class="order_qty"><div class="quick_order_fields"><div class="gift_quick_order_size">&nbsp;</div><div class="gift_quick_order_qty"><strong class="dgrey">');
    sb.append(SR.Quantity);
    sb.append('</strong></div></div>');
    sb.append('<div class="quick_order_fields"><div class="gift_quick_order_size">&nbsp;</div><div class="gift_quick_order_qty">');

    if (cartItem.ProductType == 'BusinessPrintingExternal')
    {
        sb.append('<input type="text" size="2" maxlength="3" value="');
        sb.append(cartItem.Quantity);
        sb.append('" readonly="readonly" style="background-color:#f4f4f4;border:0px;" id="qty_');
        sb.append(groupID);
        sb.append('"/>');

    }
    else
    {
        sb.append('<input type="text" size="2" maxlength="3" value="');
        sb.append(cartItem.Quantity);
        sb.append('" onkeyup="QuantityChanged(this, \'');
        sb.append(groupID);
        sb.append('\');" id="qty_');
        sb.append(groupID);
        sb.append('"/>');
    }
    
    sb.append('</div></div>');
    sb.append('</div>');
    sb.append('</div>');

    return sb.toString();
}

function onPackageQuantityChanged(groupID, optionValueID)
{
    var cartItem = shoppingCart.getCartItemByGroupID(groupID);
    
    shoppingCart.lockCartItemForEdit(cartItem);
    cartItem.PackageOptionValue.EncOptionValueID = optionValueID;
    shoppingCart.unlockCartItem(cartItem);

    var lblPrice = $get('price_' + groupID);
    
    for (var i = 0; i < cartItem.PackageOption.Values.length; i++)
    {
        var value = cartItem.PackageOption.Values[i];
        
        if (value.EncOptionValueID == optionValueID)
        {
            cartItem.Price = value.Price;
            lblPrice.innerHTML = value.Price.toFixed(2);
            break;
        }
    }
}

function onExpandEnlargementsClick(groupID)
{
    var cartItem = shoppingCart.getCartItemByGroupID(groupID);
    var enlargments = document.getElementById('enlargements_' + groupID);
    var button = document.getElementById('enlargements_button_' + groupID);

    if (enlargments === null)
    {
        var container = document.getElementById('enlargements_container_' + groupID);
        var html = RenderPrintSubItemHTML(5, cartItem.SubItems.length, groupID, cartItem.SubItems, printSizes);
        container.innerHTML = html;
        container.id = 'enlargements_' + groupID;
        button.innerHTML = SR.OrderSmallPrints;
    }
    else
    {
        var state = enlargments.style.display;
        state = state == '' ? 'none' : '';

        if (state == 'none')
        {
            button.innerHTML = SR.OrderEnlargementPrints;
        }
        else
        {
            button.innerHTML = SR.OrderSmallPrints;
        }

        enlargments.style.display = state;
    }
}

var quickSetQuantities = null;
var quickSetValid = null;

function getPrintSizeIndexByRetailerProductID(retailerProductID)
{
    for (var i = 0; i < printSizes.length; i++)
    {
        if (printSizes[i].EncRetailerProductID == retailerProductID)
        {
            return i;
        }
    }
    return null;
}

function getQuickSetQuantity(retailerProductID)
{
    var element = document.getElementById('qdd_' + retailerProductID);
    var index = getPrintSizeIndexByRetailerProductID(retailerProductID);

    if (element != null)
    {
        var q = parseInt(element.value);

        if (isNaN(q))
        {
            return quickSetQuantities[index];
        }

        return q;
    }

    return quickSetQuantities[index];
}

function getQuickSetSurfaceOptionValueID(retailerProductID)
{
    var print = shoppingCart.getPrintSizeInfoByRetailerProductID(retailerProductID);
    var element = document.getElementById('surface_' + retailerProductID);

    if (element == null)
    {
        return print.SurfaceOption.SelectedOptionValueID;
    }

    return element.options[element.selectedIndex].value;
}

function getQuickSetBorderOptionValueID(retailerProductID)
{
    var print = shoppingCart.getPrintSizeInfoByRetailerProductID(retailerProductID);
    var element = document.getElementById('quickset_border_' + retailerProductID);

    if (element == null)
    {
        if (print.BorderOption)
        {
            return print.BorderOption.SelectedOptionValueID;
        }
        else
        {
            return null;
        }
    }

    var findName = element.src.indexOf('_on') > 0 ? 'True' : 'False';

    for (var i = 0; i < print.BorderOption.Values.length; i++)
    {
        if (print.BorderOption.Values[i].Name == findName)
        {
            return print.BorderOption.Values[i].EncOptionValueID;
        }
    }

    return print.BorderOption.DefaultOptionValueID;
}

function hasQuickSetQuantityChanged(printSizeIndex)
{
    var print = printSizes[printSizeIndex];
    var retailerProductID = print.EncRetailerProductID;
    return getQuickSetQuantity(retailerProductID) != quickSetQuantities[printSizeIndex];
}

function hasQuickSetSurfaceChanged(printSizeIndex)
{
    var print = printSizes[printSizeIndex];
    var retailerProductID = print.EncRetailerProductID;
    return getQuickSetSurfaceOptionValueID(retailerProductID) != print.SurfaceOption.SelectedOptionValueID;
}

function hasQuickSetBorderChanged(printSizeIndex)
{
    var print = printSizes[printSizeIndex];
    var retailerProductID = print.EncRetailerProductID;

    if (print.BorderOption)
    {
        return getQuickSetBorderOptionValueID(retailerProductID) != print.BorderOption.SelectedOptionValueID;
    }

    return false;
}

function quickSetItemHasChanged(retailerProductID)
{
    var print = shoppingCart.getPrintSizeInfoByRetailerProductID(retailerProductID);
    var index = getPrintSizeIndexByRetailerProductID(retailerProductID);

    var quantityChanged = hasQuickSetQuantityChanged(index);

    if (quantityChanged)
    {
        return true;
    }

    var surfaceChanged = hasQuickSetSurfaceChanged(index);
    var borderChanged = hasQuickSetBorderChanged(index);

    return surfaceChanged || borderChanged;
}

function evaluateShowQuickSetApplyButton()
{
    var changed = false;

    for (var i = 0; i < printSizes.length; i++)
    {
        if (quickSetItemHasChanged(printSizes[i].EncRetailerProductID))
        {
            changed = true;
            break;
        }
    }

    quickSetApplyButton.style.display = changed ? '' : 'none';
    quickSetDisabledButton.style.display = changed ? 'none' : '';
}

function quickSetQuantityChanged(sender, retailerProductID)
{
    if (sender.value != '' && isNaN(sender.value))
    {
        sender.value = '0';
    }
    evaluateShowQuickSetApplyButton();
}

function quickSetSurfaceChanged(sender, retailerProductID)
{
    evaluateShowQuickSetApplyButton();
}

function quickSetBorderChanged(sender, retailerProductID)
{
    var on = sender.src.indexOf('_on') > 0;
    sender.src = '../images/img_checkbox_' + (on ? 'off' : 'on') + '.gif';
    evaluateShowQuickSetApplyButton();
}

function onRenderComplete(sender, args)
{
    updateTotalPrice();

    if (shoppingCart.getNumProductsInCartByType('Prints') > 0)
    {
        var quickSetInfo = shoppingCart.getQuickSetInitialQuantities();
        quickSetQuantities = new Array();
        quickSetValid = new Array();

        for (var i = 0; i < quickSetInfo.length; i++)
        {
            if (quickSetInfo[i] != null)
            {
                if (i > 5 && quickSetInfo[i] > 0)
                {
                    showQuickSetEnlargements();
                }

                quickSetQuantities.push(quickSetInfo[i]);
                quickSetValid.push(true);
                document.getElementById('qdd_' + printSizes[i].EncRetailerProductID).value = quickSetInfo[i];
            }
            else
            {
                quickSetQuantities.push(0);
                quickSetValid.push(false);
                document.getElementById('qdd_' + printSizes[i].EncRetailerProductID).value = '-';
            }
        }
    }

    cartLoadComplete = true;

    if (currentUIRenderRequests === 0)
    {
        hideLoadingPopup();
        //verifyCartItemsOnDocument();
    }
}

function showQuickSetEnlargements()
{
    document.getElementById('QuickSetShowEnlargementsButton').style.display = 'none';
    document.getElementById('QuickSetHideEnlargementsButton').style.display = '';
    document.getElementById('quickset_enlargements').style.display = '';
}

function hideQuickSetEnlargements()
{
    document.getElementById('QuickSetShowEnlargementsButton').style.display = '';
    document.getElementById('QuickSetHideEnlargementsButton').style.display = 'none';
    document.getElementById('quickset_enlargements').style.display = 'none';
}

function onQuickSetApplyClick()
{
    var batchZero = new Array();
    var batch = new Array();

    for (var i = 0; i < printSizes.length; i++)
    {
        var print = printSizes[i];
        var quantityChanged = hasQuickSetQuantityChanged(i);
        var surfaceChanged = hasQuickSetSurfaceChanged(i);
        var borderChanged = hasQuickSetBorderChanged(i);
        var batchObject = new Object();

        if (!quantityChanged && !surfaceChanged && !borderChanged)
        {
            continue;
        }

        batchObject.EncRetailerProductID = print.EncRetailerProductID;

        if (quantityChanged)
        {
            quickSetQuantities[i] = getQuickSetQuantity(print.EncRetailerProductID);
            quickSetValid[i] = true;
            batchObject.Quantity = quickSetQuantities[i];
        }

        if (surfaceChanged || borderChanged)
        {
            batchObject.Options = new Array();
        }

        if (surfaceChanged)
        {
            var surfaceValue = getQuickSetSurfaceOptionValueID(print.EncRetailerProductID);

            batchObject.Options.push(
                                        {
                                            EncOptionID: print.SurfaceOption.EncOptionID,
                                            EncOptionValueID: surfaceValue
                                        });

            print.SurfaceOption.SelectedOptionValueID = surfaceValue;
        }

        if (borderChanged)
        {
            var borderValue = getQuickSetBorderOptionValueID(print.EncRetailerProductID);

            batchObject.Options.push(
                                        {
                                            EncOptionID: print.BorderOption.EncOptionID,
                                            EncOptionValueID: borderValue
                                        });

            print.BorderOption.SelectedOptionValueID = borderValue;
        }

        if (batchObject.Quantity && batchObject.Quantity == 0)
        {
            batchZero.push(batchObject);
        }
        else
        {
            batch.push(batchObject);
        }
    }

    for (var i = 0; i < batchZero.length; i++)
    {
        batch.push(batchZero[i]);
    }

    if (batch.length == 0 && optionBatch.length == 0)
    {
        this.quickSetWarningPopupFunction("Nothing to update.");
        return;
    }

    var callbacks =
    {
        onBeginEditCartItem: onQuickSetCartItemBeginUpdate,
        onSubItemQuantityChanged: onQuickSetSubItemQuantityChanged,
        onSubItemSurfaceChanged: onQuickSetSubItemSurfaceChanged,
        onSubItemBorderChanged: onQuickSetSubItemBorderChanged,
        onEndEditCartItem: onQuickSetCartItemEndUpdate
    };

    evaluateShowQuickSetApplyButton();

    shoppingCart.updateQuickSet(batch, callbacks);
    showLoadingPopupDelayed();
    ShowCartItemCount(shoppingCart.getCartItemsCount());
}

function checkForPrintsInCart()
{
    if (shoppingCart.getNumProductsInCartByType('Prints') == 0)
    {
        PhotoCDQuantityChanged(false);
        document.getElementById('PhotoCDSection').style.display = 'none';
        document.getElementById('QuickOrderSection').style.display = 'none';
    }
}

function onUpdateQuickSetComplete()
{
    checkForPrintsInCart();
    updateTotalPrice();
    hideLoadingPopup();
}

var currentCartItemContainerDiv = null;

function onQuickSetCartItemBeginUpdate(sender, cartItem)
{
    currentCartItemContainerDiv = document.getElementById('container_' + cartItem.GroupID);
    //currentCartItemContainerDiv.style.display = 'none';
}

function onQuickSetCartItemEndUpdate(sender, cartItem, isDeleted, isQuantityUpdated)
{
    if (isDeleted)
    {
        document.getElementById('container_' + cartItem.GroupID).style.display = 'none';
        return;
    }
    if (isQuantityUpdated)
    {
        var price_div = document.getElementById('price_' + cartItem.GroupID);
        price_div.innerHTML = shoppingCart.calculatePrintPrice(cartItem).toFixed(2);
    }
    //currentCartItemContainerDiv.style.display = '';
}

function evalSubItemCropWarning(cartItem, subItem)
{
    //                                if (subItem.WarnCrop == false)
    //                                {
    //                                    return;
    //                                }

    var warnCrop = document.getElementById('warncrop_' + cartItem.GroupID + '_' + subItem.EncRetailerProductID);

    if (warnCrop === null)
    {
        return;
    }

    warnCrop.style.display = (subItem.Quantity > 0 && subItem.WarnCrop) ? '' : 'none';
}

function evalSubItemResolutionWarning(cartItem, subItem)
{
    //                                if (subItem.WarnRes == false)
    //                                {
    //                                    return;
    //                                }

    var warnres = document.getElementById('warnres_' + cartItem.GroupID + '_' + subItem.EncRetailerProductID);

    if (warnres == null)
    {
        return;
    }

    warnres.style.display = (subItem.Quantity > 0 && subItem.WarnRes) ? '' : 'none';
}

function onQuickSetSubItemQuantityChanged(sender, cartItem, subItem, index, evaluateWarnings)
{
    var groupID = cartItem.GroupID;
    var rpID = subItem.EncRetailerProductID;

    var qty = document.getElementById('qty_' + groupID + '_' + rpID);

    if (qty != null)
    {
        qty.value = subItem.Quantity;
    }
    else
    {
        qty = document.getElementById('qty_div_' + groupID + '_' + index);

        if (qty != null)
        {
            qty.innerHTML = subItem.Quantity;
        }
    }

    if (evaluateWarnings)
    {
        evalSubItemResolutionWarning(cartItem, subItem);
        evalSubItemCropWarning(cartItem, subItem);
    }
}

function onQuickSetSubItemBorderChanged(sender, cartItem, subItem)
{
    var img = document.getElementById('border_' + cartItem.GroupID + '_' + subItem.EncRetailerProductID);
    if (img) img.src = '../images/img_checkbox_' + (subItem.PrintBorder.Name == 'True' ? 'on' : 'off') + '.gif';
}

function onQuickSetSubItemSurfaceChanged(sender, cartItem, subItem)
{
    var div = document.getElementById('surface_' + cartItem.GroupID + '_' + subItem.EncRetailerProductID);
    if (div) div.innerHTML = subItem.PrintSurface.Name;
}

var currentCartTotal = 0;

function updateTotalPriceWithDelta(delta)
{
    currentCartTotal += delta;
    document.getElementById('totalCartAmount').innerHTML = currentCartTotal.toFixed(2);
}

function updateTotalPrice()
{
    currentCartTotal = shoppingCart.calculateCartTotalPrice();

    if (cdCartItem)
    {
        currentCartTotal -= (cdCartItem.Price * cdCartItem.Quantity);
    }

    currentCartTotal += cdPrice;
    
    document.getElementById('totalCartAmount').innerHTML = currentCartTotal.toFixed(2);
}

function quantityFromTextBox(txtbox)
{
    var q = 0;

    if (isNaN(txtbox.value))
    {
        if (txtbox.value != '')
        {
            var u = parseInt(txtbox.value);

            if (!isNaN(u))
            {
                q = u;
            }
            
            txtbox.value = q;
        }
    }
    else
    {
        q = parseInt(txtbox.value);
    }

    return q;
}

function QuantityChanged(txtbox, groupID)
{
    var cartItem = shoppingCart.getCartItemByGroupID(groupID);
    var quantity = quantityFromTextBox(txtbox);

    shoppingCart.lockCartItemForEdit(cartItem);
    {
        cartItem.Quantity = parseInt(quantity);
    }
    shoppingCart.unlockCartItem(cartItem);

    document.getElementById('price_' + groupID).innerHTML = shoppingCart.calculateCartItemPrice(cartItem).toFixed(2);

    updateTotalPrice();
}

function printQuantityDivClicked(div, groupID, index, focus)
{
    var parent = div.parentNode;
    parent.removeChild(div);

    var cartItem = shoppingCart.getCartItemByGroupID(groupID);
    var subItem = cartItem.SubItems[index];

    var sb = new PhotoSite.Framework.StringBuilder();

    sb.append('<input maxlength="3" id="qty_');
    sb.append(groupID);
    sb.append('_');
    sb.append(subItem.EncRetailerProductID);
    sb.append('" type="text" value="');
    sb.append(subItem.Quantity);
    sb.append('" onkeyup="PrintQuantityChanged(this, \'');
    sb.append(groupID);
    sb.append('\', ');
    sb.append(index);
    sb.append(');">');

    parent.innerHTML = sb.toString();

    if (focus)
    {
        var input = parent.firstChild;
        input.focus();
        input.select();
    }

    if (index > 0)
    {
        covertPrintDivToInput(groupID, index - 1);
    }

    if (++index < cartItem.SubItems.length)
    {
        covertPrintDivToInput(groupID, index);
    }
}

function covertPrintDivToInput(groupID, index)
{
    var div = document.getElementById('qty_div_' + groupID + '_' + index);

    if (div)
    {
        setTimeout(function(d, grp, idx) { return function() { printQuantityDivClicked(d, grp, idx, false); }; } (div, groupID, index), 0);
    }
}

function PrintQuantityChanged(txtbox, groupID, index)
{
    var cartItem = shoppingCart.getCartItemByGroupID(groupID);
    var quantity = quantityFromTextBox(txtbox);

    var oldPrice = shoppingCart.calculatePrintPrice(cartItem);

    shoppingCart.lockCartItemForEdit(cartItem);
    {
        cartItem.SubItems[index].Quantity = parseInt(quantity);
    }
    shoppingCart.unlockCartItem(cartItem);

    var newPrice = shoppingCart.calculatePrintPrice(cartItem);

    document.getElementById('price_' + groupID).innerHTML = newPrice.toFixed(2);

    evalSubItemResolutionWarning(cartItem, cartItem.SubItems[index]);
    evalSubItemCropWarning(cartItem, cartItem.SubItems[index]);

    updateTotalPriceWithDelta(newPrice - oldPrice);

    if (quickSetValid[index])
    {
        if (quickSetQuantities[index] != quantity)
        {
            quickSetValid[index] = false;
            quickSetQuantities[index] = null;
            document.getElementById('qdd_' + cartItem.SubItems[index].EncRetailerProductID).value = '-';
        }
    }
}

function PrintingOnBackChanged(txtBox, groupID)
{
    setTimeout(function(txtBox, groupID)
    {
        return function()
        {
            PrintingOnBackChangedCallback(txtBox, groupID);
        };
    } (txtBox, groupID), 10);
}

function PrintingOnBackChangedCallback(txtBox, groupID)
{
    var cartItem = shoppingCart.getCartItemByGroupID(groupID);
    var text = txtBox.value;

    shoppingCart.lockCartItemForEdit(cartItem);
    {
        cartItem.BackPrinting.Text = text;
    }
    shoppingCart.unlockCartItem(cartItem);

    document.getElementById('backprinting_chars_' + groupID).innerHTML = backPrintingMaxChars - text.length;
}

function backToAlbumChanged(element, groupID)
{
    var cartItem = shoppingCart.getCartItemByGroupID(groupID);
    var enhanceInfo = shoppingCart.getEditableProductOptionInfoByGroupID(groupID);

    for (var i = 0; i < enhanceInfo.ProductOption.Values.length; i++)
    {
        var value = enhanceInfo.ProductOption.Values[i];

        if (value.EncOptionValueID !== cartItem.BackToAlbum.EncOptionValueID)
        {
            shoppingCart.lockCartItemForEdit(cartItem);
            cartItem.BackToAlbum.EncOptionValueID = value.EncOptionValueID;
            cartItem.BackToAlbum.Name = value.Name;
            shoppingCart.unlockCartItem(cartItem);
            break;
        }
    }

    element.src = '../images/img_checkbox_' + (cartItem.BackToAlbum.Name == 'Yes' ? 'on' : 'off') + '.gif';
}

function SubItemBorderChanged(element, groupID, rpID)
{
    var printSize = shoppingCart.getPrintSizeInfoByRetailerProductID(rpID);
    var cartItem = shoppingCart.getCartItemByGroupID(groupID);
    var subItem = null;

    for (var i = 0; i < cartItem.SubItems.length; i++)
    {
        if (cartItem.SubItems[i].EncRetailerProductID == rpID)
        {
            subItem = cartItem.SubItems[i];
            break;
        }
    }

    shoppingCart.lockCartItemForEdit(cartItem);
    {
        var optionValueID = subItem.PrintBorder.EncOptionValueID;

        for (var i = 0; i < printSize.BorderOption.Values.length; i++)
        {
            if (printSize.BorderOption.Values[i].EncOptionValueID != optionValueID)
            {
                subItem.PrintBorder.EncOptionValueID = printSize.BorderOption.Values[i].EncOptionValueID;
                subItem.PrintBorder.Name = printSize.BorderOption.Values[i].Name;
                break;
            }
        }
    }
    shoppingCart.unlockCartItem(cartItem);

    element.src = '../images/img_checkbox_' + (subItem.PrintBorder.Name == 'True' ? 'on' : 'off') + '.gif';
}

function onPhotoPreviewClick(groupID)
{
    var cartItem = shoppingCart.getCartItemByGroupID(groupID);
    window.location = '../album/prints_preview.aspx?q=' + cartItem.EncID + '&origin=cart';
}

function onCartItemRemoveClick(groupID)
{
    var cartItem = shoppingCart.getCartItemByGroupID(groupID);
    var price = shoppingCart.calculateCartItemPrice(cartItem);
    updateTotalPriceWithDelta(-price);
    shoppingCart.deleteCartItemByGroupID(groupID);
    document.getElementById('container_' + groupID).style.display = 'none';

    if (cartItem.ProductType == 'Prints')
    {
        checkForPrintsInCart();
        updateArchiveCDInfo();
    }

    ShowCartItemCount(shoppingCart.getCartItemsCount());
}

function onSyncCartItem(sender, cartItem)
{
    if (cartItem.ProductType == 'Prints')
    {
        for (var i = 0; i < cartItem.SubItems.length; i++)
        {
            var subItem = cartItem.SubItems[i];

            if (subItem.PrintBorder)
            {
                var border = document.getElementById('border_' + cartItem.GroupID + '_' + subItem.EncRetailerProductID);

                if (border != null)
                {
                    border.src = '../images/img_checkbox_' + (subItem.PrintBorder.Name == 'True' ? 'on' : 'off') + '.gif';
                }
            }
        }
    }
}

function onEmpyCartClick()
{
    msgBox.Show(SR.EmptyCart, SR.AreYouSureEmptyCart, [{ Button: 'Cancel' }, { Button: 'OK', Callback: onEmpyCartConfirm}]);
}

function onEmpyCartConfirm()
{
    shoppingCart.emptyCart();
}

function onEmptyCartComplete()
{
    document.location = '../album/default.aspx';
}

function onContinueShoppingClick()
{
    if (shoppingCart.isWaitingForSync())
    {
        showLoadingPopup();
        shoppingCart.syncAllNow();
        setTimeout(function() { onContinueShoppingClick(); }, 500);
    }
    else
    {
        document.location = '../album/default.aspx';
    }
}

function onContinueCheckoutClick()
{
    if (shoppingCart.hasCropWarningSet())
    {
        var Message = SR.CroppingWarning;
        Message += "<br />";
        Message += "<br />";
        Message += SR.PleaseClickTheCropIcon;
        Message += '&nbsp;<img src="../images/crop_icon' + SR.LanguageSuffix + '.jpg">&nbsp;';
        Message += SR.PleaseClickTheCropIcon2;
        msgBox.Show(SR.ImageCropping, Message, [{ Button: 'Ok', Callback: continueCheckout }, { Button: 'Cancel'}], { Height: 170 });
    }
    else
    {
        continueCheckout();
    }
}

function continueCheckout()
{
    showLoadingPopup();
    shoppingCart.set_zeroQuantitySyncEnabled(true);

    if (shoppingCart.isWaitingForSync())
    {
        shoppingCart.syncAllNow();
        setTimeout(function() { continueCheckout(); }, 500);
    }
    else
    {
        var encID = cdCartItem ? cdCartItem.EncID : null;
        var cdQty = cdPrice ? 1 : 0;

        cartService.UpdatePhotoCD(encID, cdQty, indexCDUpdated, OnError);
    }
}

function indexCDUpdated(result)
{
    document.location = 'delivery_option.aspx';
}

function showCropper(groupID, rpID)
{
    rpID = rpID ? rpID : -1;
    
    if (shoppingCart.isCartItemWaitingForSync(groupID) || shoppingCart.isCartItemDataOutOfDate(groupID))
    {
        shoppingCart.syncCartItem(groupID);
        setTimeout(function(groupID, rpID) { return function() { showCropper(groupID, rpID); }; } (groupID, rpID), 500);
    }
    else
    {
        var cartItem = shoppingCart.getCartItemByGroupID(groupID);
        var validQty = false;

        for (var i = 0; i < cartItem.SubItems.length; i++)
        {
            if (cartItem.SubItems[i].Quantity > 0)
            {
                validQty = true;
                break;
            }
        }

        if (validQty === true)
        {
            if (Sys.Browser.agent == Sys.Browser.Firefox)
            {
                scroll(0, 0);
            }
            cropEditorInit(cartItem, rpID);
            PopupCropper.show();
        }
    }
}

function PhotoCDQuantityChanged(checked)
{
    if (checked)
    {
        //  var cds = shoppingCart.calculateCDsNeededForPrints();
        var cds = archiveCDInfo.NumberCDInSet;
        cdPrice = cds > 0 ? orderCDPrices[cds - 1] : 0;
    }
    else
    {
        cdPrice = 0;
    }
    document.getElementById('photoCDPrice').innerHTML = cdPrice.toFixed(2);
    updateTotalPrice();
}

//
// Needed functions from old code...
//

function hideCroppingEditorPopup()
{
    PopupCropper.hide();
}

function UpdateResolutionWarning(cartItem)
{
    for (var i = cartItem.SubItems.length - 1; i >= 0; --i)
    {
        var subItem = cartItem.SubItems[i];

        if (subItem.Quantity == 0)
        {
            continue;
        }

        subItem.WarnCrop = false;

        var warnRes = document.getElementById('warnres_' + cartItem.GroupID + '_' + subItem.EncRetailerProductID);
        var warnCrop = document.getElementById('warncrop_' + cartItem.GroupID + '_' + subItem.EncRetailerProductID);

        if (warnRes !== null)
        {
            if (subItem.WarnRes)
            {
                warnRes.style.display = '';
            }
            else
            {
                warnRes.style.display = 'none';
            }
        }
        if (warnCrop !== null)
        {
            if (subItem.WarnCrop)
            {
                warnCrop.style.display = '';
            }
            else
            {
                warnCrop.style.display = 'none';
            }
        }
    }
}

function newUpdateCropImage()
{
    var groupID = currentCropEditorCartItem.GroupID;
    var cartItem = shoppingCart.getCartItemByGroupID(groupID);

    var EncID = null;

    for (var i = 0; i < cartItem.SubItems.length; i++)
    {
        if (cartItem.SubItems[i].Quantity && cartItem.SubItems[i].EncID != '')
        {
            EncID = cartItem.SubItems[i].EncID;
            break;
        }
    }

    var printGroupedThumbnail = new Object();
    printGroupedThumbnail.eOrderItemId = EncID;
    printGroupedThumbnail.thumbnailHtmlId = groupID;
    cartService.GetGroupedOrderItemThumbnailUrl(printGroupedThumbnail, gotUpdatedCropImage, OnError, groupID);
}

function updateCropImage()
{
    newUpdateCropImage();
}

function gotUpdatedCropImage(result, context)
{
    var cartItem = shoppingCart.getCartItemByGroupID(context);
    cartItem.ThumbUrl = result.thumbnailUrl;
    var img = document.getElementById('img_' + context);
    img.src = cartItem.ThumbUrl;
}

function OnError(result)
{
    var response = confirm('an unexpected error was detected: ' + result.get_message() + '\n Would you like to empty your cart?');
    if (response)
    {
        onEmpyCartClick();
    }
}


// For new ArchiveCD limitation implementation
function updateArchiveCDInfo() {
    if (shoppingCart.getNumProductsInCartByType('Prints') > 0 && typeof (archiveCDInfo) != "undefined") {
        var m = 0;
        var arrayMediaID = new Array();
        archiveCDInfo.TotalSizeOfImages = 0;
        archiveCDInfo.TotalNumberOfImages = 0;
        archiveCDInfo.NumberCDInSet = 1;
        var tempSizeOfImages = 0;
        var tempNumOfImages=0
        for (var i = 0; i < shoppingCart._cartItems.length; i++) {
            var cartItem = shoppingCart._cartItems[i];
            if (cartItem.ProductType == "Prints" && !detectItem(arrayMediaID, cartItem.MediaID)) {
                arrayMediaID.push(cartItem.MediaID)
                tempNumOfImages++;
                tempSizeOfImages += cartItem.FileSize;
                archiveCDInfo.TotalSizeOfImages += cartItem.FileSize;
                archiveCDInfo.TotalNumberOfImages++;
                if (tempSizeOfImages > archiveCDInfo.LimitSizeOfImages || tempNumOfImages > archiveCDInfo.LimitImagesOnCD) {
                    archiveCDInfo.NumberCDInSet++;
                    tempSizeOfImages = 0;
                    tempNumOfImages = 0;
                }
                m++;
            }
        }
        SetUpArchiveCDInfo();
    }
}
    function detectItem(Array, item) {
        var j = 0;
        while (j < Array.length) {
            if (Array[j] == item) {
                return true;
            }
            else
            { j++; }
        }
        return false;
    }    


function getArchiveCDInfo() {
    cartService.GetArchiveCDInfo(getArchiveCDInfo_Result, gotError);
}

function getArchiveCDInfo_Result(result) {
    if (result) {
        archiveCDInfo = Sys.Serialization.JavaScriptSerializer.deserialize(result);
        SetUpArchiveCDInfo();
    }
}

// Constructor function for the Cropper class.
function Cropper() {
}

// Fields and methods for the Cropper class.
Cropper.prototype = {

    // Configuration fields

    grayLayerColor: '#b4e6ff',
    grayLayerOpacity: 0.7,

    moveCursor: 'move',

    resizeHandleWidth: 8,
    resizeHandleHeight: 8,
    resizeHandleColor: '#FA9E18',
    resizeHandleImage: '../images/CropGrabHandleCircle.gif',

    resizeHandleNWCursor: 'nw-resize',
    resizeHandleNECursor: 'ne-resize',
    resizeHandleSWCursor: 'nw-resize',
    resizeHandleSECursor: 'ne-resize',
    
    cropStarted: false,
    borderWidth: 1,
    
    baseObject: null,

    // Public methods

    startCropping: function(imageID, initialWidth, initialHeight, proportionWidth, proportionHeight, minWidth, minHeight, onUpdate)
    {
        this.image = $get(imageID);

        var initialLeft = cropLeft = Math.round((this.image.offsetWidth - initialWidth) / 2);
        var initialTop = Math.round((this.image.offsetHeight - initialHeight) / 2);
        
        this.startCroppingEx(imageID, initialLeft, initialTop, initialWidth, initialHeight, proportionWidth, proportionHeight, minWidth, minHeight, onUpdate);
    },

    startCroppingEx: function(imageID, initialLeft, initialTop, initialWidth, initialHeight, proportionWidth, proportionHeight, minWidth, minHeight, onUpdate)
    {
        if (this.cropStarted)
        {
            this.stopCropping();
        }
    
        this.image = $get(imageID);

        this.cropLeft = initialLeft;
        this.cropTop = initialTop;
        this.cropWidth = initialWidth;
        this.cropHeight = initialHeight;
        this.proportionWidth = proportionWidth;
        this.proportionHeight = proportionHeight;
        this.minWidth = minWidth;
        this.minHeight = minHeight;
        this.onUpdate = onUpdate;

        this.addLayersContainer();
        this.addGrayLayer();
        this.addCropLayer();
        this.addResizeHandles();
        this.addMouseDownHandlers();
        
        this.cropStarted = true;

        this.raiseUpdate();
    },

    stopCropping: function() {
        if (this.grayLayer != null)
        {
            this.grayLayer.parentNode.removeChild(this.grayLayer);
            this.grayLayer = null;
        }
        
        if (this.cropLayer != null)
        {
            this.cropLayer.parentNode.removeChild(this.cropLayer);
            this.cropLayer = null;
        }
        
        if (this.layersContainer != null)
        {
            this.layersContainer.parentNode.removeChild(this.layersContainer);
            this.layersContainer = null;
        }
        
        this.cropStarted = false;
    },

    getCropInfo: function() {
        return {
            left: this.cropLeft,
            top: this.cropTop,
            width: this.cropWidth,
            height: this.cropHeight
        };
    },

    // Private fields

    image: null,

    cropLeft: null,
    cropTop: null,
    cropWidth: null,
    cropHeight: null,

    proportionWidth: null,
    proportionHeight: null,

    minWidth: null,
    minHeight: null,

    onUpdate: null,

    layersContainer: null,
    grayLayer: null,
    cropLayer: null,

    resizeHandleNW: null,
    resizeHandleNE: null,
    resizeHandleSW: null,
    resizeHandleSE: null,

    resizingHandle: null,

    oldGrayLayerCursor: null,
    oldCropLayerCursor: null,

    lastMousePosition: null,

    // Private methods

    addLayersContainer: function() {
        this.layersContainer = document.createElement('div');
        this.layersContainer.style.position = 'absolute';
        this.image.parentNode.insertBefore(this.layersContainer, this.image);
    },

    addGrayLayer: function() {
        this.grayLayer = document.createElement('div');
        this.grayLayer.style.position = 'absolute';
        this.grayLayer.style.width = this.image.offsetWidth + 'px';
        this.grayLayer.style.height = this.image.offsetHeight + 'px';
        this.grayLayer.style.backgroundColor = this.grayLayerColor;
        this.grayLayer.style.opacity = this.grayLayerOpacity;
        this.grayLayer.style.filter = 'alpha(opacity=' + (this.grayLayerOpacity * 100)  + ')';
        this.layersContainer.appendChild(this.grayLayer);
    },

    addCropLayer: function() {
        this.cropLayer = document.createElement('div');
        this.cropLayer.style.position = 'absolute';
        this.cropLayer.style.left = (this.cropLeft - this.borderWidth) + 'px';
        this.cropLayer.style.top = (this.cropTop - this.borderWidth) + 'px';
        this.cropLayer.style.width = this.cropWidth + 'px';
        this.cropLayer.style.height = this.cropHeight + 'px';
        this.cropLayer.style.border = this.borderWidth + 'px dashed white';
        this.cropLayer.style.backgroundImage = 'url(' + this.image.src + ')';
        this.cropLayer.style.backgroundPosition = String.format('-{0}px -{1}px', this.cropLeft, this.cropTop);
        this.cropLayer.style.cursor = this.moveCursor;
        this.layersContainer.appendChild(this.cropLayer);
    },

    addResizeHandles: function() {
        this.resizeHandleNW = this.createResizeHandle(this.resizeHandleNWCursor);
        this.resizeHandleNE = this.createResizeHandle(this.resizeHandleNECursor);
        this.resizeHandleSW = this.createResizeHandle(this.resizeHandleSECursor);
        this.resizeHandleSE = this.createResizeHandle(this.resizeHandleSWCursor);
        this.setResizeHandleLocations();
    },

    createResizeHandle: function(cursor) {
        var handle = document.createElement('div');
        handle.style.position = 'absolute';
        handle.style.width = this.resizeHandleWidth + 'px';
        handle.style.height = this.resizeHandleHeight + 'px';
        handle.style.backgroundColor = ''; //this.resizeHandleColor;
        handle.style.background = 'url(' + this.resizeHandleImage +')';
        handle.style.cursor = cursor;
        handle.style.overflow = 'hidden';
        this.cropLayer.appendChild(handle);
        return handle;
    },

    setResizeHandleLocations: function() {
        var halfWidth = this.resizeHandleWidth / 2;
        var halfHeight = this.resizeHandleHeight / 2;
        this.setElementLocation(this.resizeHandleNW, -this.resizeHandleWidth + halfWidth, -this.resizeHandleHeight + halfHeight);
        this.setElementLocation(this.resizeHandleNE, this.cropWidth - halfWidth, -this.resizeHandleHeight + halfHeight);
        this.setElementLocation(this.resizeHandleSW, -this.resizeHandleWidth + halfWidth, this.cropHeight - halfHeight);
        this.setElementLocation(this.resizeHandleSE, this.cropWidth - halfWidth, this.cropHeight - halfHeight);
    },

    setElementLocation: function(element, left, top) {
        element.style.left = left + 'px';
        element.style.top = top + 'px';
    },

    addMouseDownHandlers: function() {
        this.startMovingHandler = Function.createDelegate(this, this.startMoving);
        $addHandler(this.cropLayer, 'mousedown', this.startMovingHandler);

        this.startResizingNWHandler = Function.createDelegate(this, this.startResizingNW);
        $addHandler(this.resizeHandleNW, 'mousedown', this.startResizingNWHandler);

        this.startResizingNEHandler = Function.createDelegate(this, this.startResizingNE);
        $addHandler(this.resizeHandleNE, 'mousedown', this.startResizingNEHandler);

        this.startResizingSWHandler = Function.createDelegate(this, this.startResizingSW);
        $addHandler(this.resizeHandleSW, 'mousedown', this.startResizingSWHandler);

        this.startResizingSEHandler = Function.createDelegate(this, this.startResizingSE);
        $addHandler(this.resizeHandleSE, 'mousedown', this.startResizingSEHandler);
    },

    startMoving: function(e) {
        e.preventDefault();

        this.removeMoveHandlers();

        this.lastMousePosition = this.getMousePositionFromRawEvent(e.rawEvent);

        this.moveCropHandler = Function.createDelegate(this, this.moveCrop);
        $addHandler(document, 'mousemove', this.moveCropHandler);

        this.stopMovingHandler = Function.createDelegate(this, this.stopMoving);
        $addHandler(document, 'mouseup', this.stopMovingHandler);

        this.isMoving = true;
    },

    moveCrop: function(e) {
        e.preventDefault();

        var currentMousePosition = this.getMousePositionFromRawEvent(e.rawEvent);

        var deltaX = currentMousePosition.x - this.lastMousePosition.x;
        var deltaY = currentMousePosition.y - this.lastMousePosition.y;

        this.cropLeft += deltaX;
        this.cropTop += deltaY;

        if (this.cropLeft < 0) {
            this.cropLeft = 0;
        }

        if ((this.cropLeft + this.cropWidth) > this.image.offsetWidth) {
            this.cropLeft = this.image.offsetWidth - this.cropWidth;
        }

        if (this.cropTop < 0) {
            this.cropTop = 0;
        }

        if ((this.cropTop + this.cropHeight) > this.image.offsetHeight) {
            this.cropTop = this.image.offsetHeight - this.cropHeight;
        }

        this.cropLayer.style.left = this.cropLeft + 'px';
        this.cropLayer.style.top = this.cropTop + 'px';

        this.setBackgroundPosition();

        this.raiseUpdate();

        this.lastMousePosition = currentMousePosition;
    },

    setBackgroundPosition: function() {
        this.cropLayer.style.backgroundPosition = String.format('-{0}px -{1}px', this.cropLeft, this.cropTop);
    },

    stopMoving: function(e) {
        e.preventDefault();
        this.removeMoveHandlers();
    },

    removeMoveHandlers: function() {
        if (this.isMoving) {
            $removeHandler(document, 'mousemove', this.moveCropHandler);
            $removeHandler(document, 'mouseup', this.stopMovingHandler);
            this.isMoving = false;
        }
    },

    startResizingNW: function(e) {
        this.startResizing(e, this.resizeHandleNW);
    },

    startResizingNE: function(e) {
        this.startResizing(e, this.resizeHandleNE);
    },

    startResizingSW: function(e) {
        this.startResizing(e, this.resizeHandleSW);
    },

    startResizingSE: function(e) {
        this.startResizing(e, this.resizeHandleSE);
    },

    startResizing: function(e, resizeHandle) {
        e.preventDefault();

        // Don't let the mousedown event bubble up to cropLayer or it
        // will startMoving will get invoked.
        e.stopPropagation();

        this.removeResizeHandlers();

        this.resizingHandle = resizeHandle;

        this.oldGrayLayerCursor = this.grayLayer.style.cursor;
        this.grayLayer.style.cursor = resizeHandle.style.cursor;

        this.oldCropLayerCursor = this.cropLayer.style.cursor;
        this.cropLayer.style.cursor = resizeHandle.style.cursor;

        this.resizeCropHandler = Function.createDelegate(this, this.resizeCrop);
        $addHandler(document, 'mousemove', this.resizeCropHandler);

        this.stopResizingHandler = Function.createDelegate(this, this.stopResizing);
        $addHandler(document, 'mouseup', this.stopResizingHandler);

        this.isResizing = true;
    },

    resizeCrop: function(e) {
        e.preventDefault();

        var cropPosition = Sys.UI.DomElement.getBounds(this.cropLayer);
        var mousePosition = this.getMousePositionFromRawEvent(e.rawEvent);

        var potentialWidth = 0;
        var potentialHeight = 0;

        // Calculate some the potential size of the crop based on the
        // current mouse position and the handle being used to resize.
        if (this.resizingHandle == this.resizeHandleNW) {
            potentialWidth = cropPosition.x - mousePosition.x + this.cropWidth;
            potentialHeight = cropPosition.y - mousePosition.y + this.cropHeight;
        } else if (this.resizingHandle == this.resizeHandleNE) {
            potentialWidth = mousePosition.x - cropPosition.x;
            potentialHeight = cropPosition.y - mousePosition.y + this.cropHeight;
        } else if (this.resizingHandle == this.resizeHandleSW) {
            potentialWidth = cropPosition.x - mousePosition.x + this.cropWidth;
            potentialHeight = mousePosition.y - cropPosition.y;
        } else {
            potentialWidth = mousePosition.x - cropPosition.x;
            potentialHeight = mousePosition.y - cropPosition.y;
        }

        var newWidth = potentialWidth;
        var newHeight = potentialHeight;

        // If necessary, update the width or height to conform to the
        // required aspect ratio.
        if (this.proportionWidth && this.proportionHeight) {
            if ((potentialWidth / potentialHeight) >= (this.proportionWidth / this.proportionHeight)) {
                newHeight = Math.round(potentialWidth * (this.proportionHeight / this.proportionWidth));
            } else {
                newWidth = Math.round(potentialHeight * (this.proportionWidth / this.proportionHeight));
            }
        }

        var newLeft = this.cropLeft;
        var newTop = this.cropTop;

        // Update left and top, if necessary.
        if (this.resizingHandle == this.resizeHandleNW) {
            newLeft = this.cropLeft + this.cropWidth - newWidth;
            newTop = this.cropTop + this.cropHeight - newHeight;
        } else if (this.resizingHandle == this.resizeHandleNE) {
            newTop = this.cropTop + this.cropHeight - newHeight;
        } else if (this.resizingHandle == this.resizeHandleSW) {
            newLeft = this.cropLeft + this.cropWidth - newWidth;
        } else {
            // Nothing to do for south-east handle.
        }

        if (false) {
            Sys.Debug.trace(String.format('cropLeft: {0}, cropTop: {1}', this.cropLeft, this.cropTop));
            Sys.Debug.trace(String.format('cropWidth: {0}, cropHeight: {1}', this.cropWidth, this.cropHeight));
            Sys.Debug.trace(String.format('deltaX: {0}, deltaY: {1}', deltaX, deltaY));
            Sys.Debug.trace(String.format('potentialWidth: {0}, potentialHeight: {1}', potentialWidth, potentialHeight));
            Sys.Debug.trace(String.format('newWidth: {0}, newHeight: {1}', newWidth, newHeight));
            Sys.Debug.trace(String.format('newLeft: {0}, newTop: {1}', newLeft, newTop));
            Sys.Debug.trace('');
        }

        var allowMinResize = ((this.cropWidth < this.minWidth) && (newWidth > this.cropWidth)) || 
                             ((this.cropHeight < this.minHeight) && (newHeight > this.cropHeight));

        // If the new bounds are valid, update the crop.
        if ((newLeft >= 0) &&
            ((newWidth >= this.minWidth) || allowMinResize) &&
            ((newLeft + newWidth) <= this.image.offsetWidth) &&
            (newTop >= 0) &&
            ((newHeight >= this.minHeight) || allowMinResize) &&
            ((newTop + newHeight) <= this.image.offsetHeight)) {

            this.cropLeft = newLeft;
            this.cropTop = newTop;
            this.cropWidth = newWidth;
            this.cropHeight = newHeight;

            this.cropLayer.style.left = this.cropLeft + 'px';
            this.cropLayer.style.top = this.cropTop + 'px';
            this.cropLayer.style.width = this.cropWidth + 'px';
            this.cropLayer.style.height = this.cropHeight + 'px';

            // Set the position of the background image to match the left
            // and top of the crop
            this.setBackgroundPosition();

            // Update the resize handle positions.
            this.setResizeHandleLocations();

            // This is a workaround for a weird rendering bug in FF that
            // only appears when the width or height changes, but left
            // and top don't. Toggling left like this shouldn't be visible
            // to the user, but doing it forces the browser to re-draw
            // cropLayer correctly.
            this.cropLayer.style.left = (this.cropLayer.offsetLeft + 1) + 'px';
            this.cropLayer.style.left = (this.cropLayer.offsetLeft - 1) + 'px';

            this.raiseUpdate();
        }
    },

    stopResizing: function(e) {
        e.preventDefault();
        this.removeResizeHandlers();
    },

    removeResizeHandlers: function() {
        if (this.isResizing) {
            this.grayLayer.style.cursor = this.oldGrayLayerCursor;
            this.cropLayer.style.cursor = this.oldCropLayerCursor;

            $removeHandler(document, 'mousemove', this.resizeCropHandler);
            $removeHandler(document, 'mouseup', this.stopResizingHandler);

            this.isResizing = false;
        }
    },

    raiseUpdate: function() {
        if (this.onUpdate) {
            this.onUpdate(this.getCropInfo(), this.baseObject);
        }
    },

    getMousePositionFromRawEvent: function(e) {
        var x = 0;
        var y = 0;
        if (e.pageX || e.pageY) {
            x = e.pageX;
            y = e.pageY;
        } else if (e.clientX || e.clientY) {
            x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
            y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
        }
        return { x: x, y: y };
    }

};


function CropArea()
{
}

CropArea.prototype = {

    image:null,
    layersContainer:null,
    backLayer:null,
    frontLayer:null,
    cropLeft:0,
    cropTop:0,
    cropRight:0,
    cropBottom:0,
    cropWidth:0,
    cropHeight:0,
    visible:false,
    grayLayerColor: '#b4e6ff',
    grayLayerOpacity: 0.7,
    borderWidth:2,

    show: function(imageID, left, top, right, bottom)
    {
        if (this.visible)
        {
            this.hide();
        }
        
        this.image = $get(imageID);
        
        this.cropTop = parseInt(top);
        this.cropLeft = parseInt(left);
        this.cropRight = parseInt(right);
        this.cropBottom = parseInt(bottom);
        this.cropWidth = this.cropRight - this.cropLeft;
        this.cropHeight = this.cropBottom - this.cropTop;
        
        this.addContainer();
        this.addBackLayer();
        this.addFrontLayer();
        this.visible = true;
    },

    setBorderWidth: function(width)
    {
        this.borderWidth = width;
    },

    hide: function()
    {
        if (this.backLayer != null)
        {
            this.backLayer.parentNode.removeChild(this.backLayer);
            this.backLayer = null;
        }
        
        if (this.frontLayer != null)
        {
            this.frontLayer.parentNode.removeChild(this.frontLayer);
            this.frontLayer = null;
        }
        
        if (this.layerContainer != null)
        {
            this.layersContainer.parentNode.removeChild(this.layersContainer);
            this.layersContainer = null;
        }
        
        this.visible = false;
    },

    addContainer: function() {
        this.layersContainer = document.createElement('div');
        this.layersContainer.style.position = 'absolute';
        this.image.parentNode.insertBefore(this.layersContainer, this.image);
    },

    addBackLayer: function() {
        this.backLayer = document.createElement('div');
        this.backLayer.style.position = 'absolute';
        this.backLayer.style.width = this.image.offsetWidth + 'px';
        this.backLayer.style.height = this.image.offsetHeight + 'px';
        this.backLayer.style.backgroundColor = this.grayLayerColor;
        this.backLayer.style.opacity = this.grayLayerOpacity;
        this.backLayer.style.filter = 'alpha(opacity=' + (this.grayLayerOpacity * 100)  + ')';
        this.layersContainer.appendChild(this.backLayer);
    },

    addFrontLayer: function()
    {
        this.frontLayer = document.createElement('div');
        this.frontLayer.style.position = 'absolute';
        this.frontLayer.style.left = (this.cropLeft - this.borderWidth) + 'px';
        this.frontLayer.style.top = (this.cropTop - this.borderWidth) + 'px';
        this.frontLayer.style.width = this.cropWidth + 'px';
        this.frontLayer.style.height = this.cropHeight + 'px';
        this.frontLayer.style.border = this.borderWidth + 'px solid black';
        this.frontLayer.style.backgroundImage = 'url(' + this.image.src + ')';
        this.frontLayer.style.backgroundPosition = String.format('-{0}px -{1}px', this.cropLeft, this.cropTop);
        this.layersContainer.appendChild(this.frontLayer);
    }


};

function CropEditor(sequenceCommandExecutor, editPhotoService){
    this.cropOrderItemPanel = new CropOrderItemPanel(this);
    this.cropEditorEditPanel = new CropEditorEditPanel(this);    
    this.cropEditorProxy = new CropEditorProxy(this, editPhotoService);
    this.sequenceCommandExecutor = sequenceCommandExecutor;
}

CropEditor.prototype = {
    
    cropOrderItemPanel: null,
    cropEditorEditPanel: null,
    cropEditorProxy: null,
    sequenceCommandExecutor: null,
    cartItems: null,
    maxThumbPhotoSize: 90,
    maxPreviewPhotoSize: 320,
    selectedRpID: null,

    init:function(icartItems, rpID)
    {
        this.selectedRpID = rpID;
        this.clearUI();
        this.cartItems = icartItems; 
        this.populateCropAspectInfo(icartItems);
    },
    
    populateCropAspectInfo:function(cartItems){
        var eOrderItemIds = new Array();
        for (var i = 0; i < cartItems.SubItems.length; i++)
        {
            if ( ((cartItems.SubItems[i].Quantity > 0)) && (cartItems.SubItems[i].EncID != ""))
            {
                Array.add(eOrderItemIds, cartItems.SubItems[i].EncID);
            }
        }
        this.cropEditorProxy.getOrderItemCropWrappers(eOrderItemIds, this.maxThumbPhotoSize, this.maxPreviewPhotoSize);
    },
    
    populateCropAspectInfoComplete:function(orderItemCropWrappers){
        var j = 0;
        for (var i = 0; i < this.cartItems.SubItems.length; i++)
        {
            if ( ((this.cartItems.SubItems[i].OrigQuantity > 0) || (this.cartItems.SubItems[i].Quantity > 0)) && (this.cartItems.SubItems[i].EncID != "") && (orderItemCropWrappers[j] != null))
            {
                this.cropOrderItemPanel.addCropOrderItemBySubOrderItem(this.cartItems.SubItems[i], orderItemCropWrappers[j]);
                j++;
            }
        }
        this.render();
    },    
    
    ImagesRenderCompleted: function (){
        if (this.cropOrderItemPanel.ImagesRenderCompleted() && this.cropEditorEditPanel.ImagesRenderCompleted())
            return true;
        return false;
    },
    
    clearUI: function () {
        this.cropOrderItemPanel.clearUI();
        this.cropEditorEditPanel.clearUI();
    },
   
    clear: function() {
        this.selectedRpID = null;
        this.cartItems = null;
        this.cropOrderItemPanel.clear();
        this.cropEditorEditPanel.clear();
        this.cropEditorProxy.clear();
    },
        
    render:function()
    {                
        this.cropOrderItemPanel.render(this.selectedRpID);        
        var cropOrderItem = this.cropOrderItemPanel.getCurrentCropOrderItem();
        this.cropEditorEditPanel.render(cropOrderItem);             
    },
    
    renderCropOverlay: function()
    {
        this.cropOrderItemPanel.renderCropOverlay();
        this.cropEditorEditPanel.renderCropOverlay();
    },
    
    saveCropEdits: function()
    {
       this.cropEditorProxy.saveOrderItemCrops(this.cropOrderItemPanel.getOrderItemCropWrappers());
    },   
    
    closeCropEditor: function()
    {        
        this.clearUI();
        this.clear();        
    },
    
    newOrderItemSelected: function()
    {
        var cropOrderItem = this.cropOrderItemPanel.getCurrentCropOrderItem();        
        this.cropEditorEditPanel.updateImage(cropOrderItem);
    },
    
    showCropper:function()
    {
        this.cropEditorEditPanel.startCropper();
    },
    
    setCropOrientation: function(sRadioBtn, orientation)
    {
        this.cropEditorEditPanel.setCropOrientation(sRadioBtn, orientation);
        this.cropEditorEditPanel.startCropper();
    },
    
    startOverCrop: function()
    {
        this.cropEditorEditPanel.startOver();
        this.cropEditorEditPanel.startOver(); //TODO TEMP FIX:call twice or else not doing the cropper right. Have to fix later. 
        this.applyCrop(); //commit change immediately when clicking undo
    },
    
    applyCrop: function()
    {
        this.cropEditorEditPanel.saveEdit();
    },
    
    changeCrop: function()
    {
        this.cropEditorEditPanel.changeCrop();
    },
    getMinimumResOrderItemMedia: function (mediaID, rpid, currentAspectRatio) {
        this.cropEditorProxy.getMinimumResOrderItemMedia(mediaID, rpid, currentAspectRatio);
    },
    getMinimumResOrderItemMediaComplete: function(result)
    {
        this.cropEditorEditPanel.onCropGotMinSize(result);
    },
    saveOrderItemCropsComplete: function()
    {
        this.sequenceCommandExecutor.CommandCompleted();
    },
    getSavedCropToJSObject: function()
    {
        for(var i = 0; i < this.cartItems.SubItems.length; i++)
        {
            var rpID = this.cartItems.SubItems[i].rpID ? this.cartItems.SubItems[i].rpID : this.cartItems.SubItems[i].EncRetailerProductID;
            var foundCartItem = this.cropOrderItemPanel.getCartItemByRPId(rpID);  
            if (foundCartItem) this.cartItems.SubItems[i].WarnRes = foundCartItem.isLowRes;
        }
        return this.cartItems;
    }    
};

//Constructor
function CropOrderItem(cropCartOrderItemPanel, subOrderItem, orderItemCropWrapper, arrayPosition){
    this.orderItem = subOrderItem;
    this.aspectRatio = orderItemCropWrapper.aspectRatio;
    this.originalLandscapeCrop = orderItemCropWrapper.cropDataLandscape;
    this.originalPortraitCrop = orderItemCropWrapper.cropDataPortrait;    
    this.startCrop = {left: orderItemCropWrapper.cropDataToSave.left, right: orderItemCropWrapper.cropDataToSave.right, top: orderItemCropWrapper.cropDataToSave.top, bottom: orderItemCropWrapper.cropDataToSave.bottom};
    this.newCrop = orderItemCropWrapper.cropDataToSave;
    this.thumbnailImageUrl = orderItemCropWrapper.smallImageUrl;
    this.largeImageUrl = orderItemCropWrapper.largeImageUrl;
    this.cropCartOrderItemPanel = cropCartOrderItemPanel;
    this.cropCartOrderItemPanel_ArrayPosition = arrayPosition;
    this.retailerProductName = orderItemCropWrapper.retailerProductName;
    this.isLandscape = orderItemCropWrapper.isLandscape;
    this.imageDivId = "img" + this.cropCartOrderItemPanel_ArrayPosition;  
    this.isLowRes = subOrderItem.WarnRes;
    this.lowResImageID = "lowResImg" + this.cropCartOrderItemPanel_ArrayPosition;  
    this.eOrderItemMediaId = orderItemCropWrapper.eOrderItemMediaId;
    this.cropIsLandscape = orderItemCropWrapper.cropIsLandscape;
    this.borderID = orderItemCropWrapper.borderID;
    this.minLengthOfWidth = orderItemCropWrapper.minLengthOfWidth;
    this.minLengthOfHeight= orderItemCropWrapper.minLengthOfHeight;    
}

CropOrderItem.prototype = {

//Class attributes
    wrapperDiv: null,
    orderItem: null,
    //orderItems: [], //to support group product by aspect ratio 
    aspectRatio: 0,
    originalLandscapeCrop: null, //default: center crop.
    originalPortraitCrop: null,
    newCrop: null,
    startCrop: null,
    thumbnailImageUrl: null,
    largeImageUrl: null,
    cropCartOrderItemPanel: null,
    cropCartOrderItemPanel_ArrayPosition: null,
    retailerProductName: "",
    isLandscape: true,
    cropArea: null,
    imageDivId: null,
    isLowRes: false,
    lowResImageID: null,
    eOrderItemMediaId: null,
    cropIsLandscape: true,
    borderID: -1,
    minLengthOfWidth: 0,
    minLengthOfHeight: 0,
    

//Class functions
//    addOrderItem: function(orderItem){
//        Array.add(this.orderItems, orderItem);
//    },

    setIsLowRes: function (isLowRes)
    {
        this.isLowRes = isLowRes;
        var lowResImage = $get(this.lowResImageID);
        if (isLowRes)
            lowResImage.style.visibility = "visible";
        else
            lowResImage.style.visibility = "hidden";
    },
    
    getRPId: function()
    {
        return this.orderItem.rpID;
    },
    
    selected: function()
    {        
        this.cropCartOrderItemPanel.itemSelected(this.cropCartOrderItemPanel_ArrayPosition);
    },
    
    setToSelected: function()
    {
        this.wrapperDiv.className = "crop_thumb_on";
    },
    
    setToUnSelected: function()
    {
        this.wrapperDiv.className = "crop_thumb";
    },  
    
    getImageURL: function() {
        return "";
    },
    
    getOrderItemCropWrapper: function() {
        var wrapper = new Object();
        wrapper.cropDataToSave = this.newCrop;
        wrapper.borderID = this.borderID;
        wrapper.eOrderItemId = this.orderItem.EncID;
        return wrapper;
    },
    
    ImagesRenderCompleted: function() {
         var img = $get(this.imageDivId);
         if (img != null)
         {
            var width = img.width;
            if ((width > 0) && (img.complete)) 
            {
                return true;
            }
         }
         return false;
    },
    
    //OrderItem structure
    //wrapperDiv
    //  innerWrapperDiv
    //     table
    //       tbody
    //          tr
    //            td
    //              img
    //     titleDiv
    //       img
    render: function() {
        //Output HTML with the crop overlay.
        this.wrapperDiv = document.createElement("div");       
        this.wrapperDiv.className = "crop_thumb";
        
        var innerWrapperDiv = document.createElement("div");
        innerWrapperDiv.style.width  = "100%";
        innerWrapperDiv.style.height = "100%";
        innerWrapperDiv.cropOrderItem = this;
        innerWrapperDiv.onclick = function () { this.cropOrderItem.selected();};
        innerWrapperDiv.style.cursor = "pointer";
        
        var table = document.createElement('table');
        var tbody = document.createElement('tbody');
        table.appendChild(tbody);
        var tr = document.createElement('tr');
        tbody.appendChild(tr);
        var td = document.createElement('td');
        tr.appendChild(td);        
        
        
        var img = document.createElement("img");
        img.setAttribute("border","0");
        img.setAttribute("align","middle");
        img.setAttribute("src", this.thumbnailImageUrl);
        img.setAttribute("id", this.imageDivId);
        
        td.appendChild(img);        
        
        innerWrapperDiv.appendChild(table);
        
        var lowResImg = document.createElement("img");
        lowResImg.setAttribute("src", "../images/icon_warning.gif");
        lowResImg.setAttribute("border", "0px");
        lowResImg.style.border = "0px";
        lowResImg.setAttribute("id", this.lowResImageID);
        if (!this.isLowRes)
        {
            lowResImg.style.visibility = 'hidden';
        }
        
        var titleDiv = document.createElement("div");
        titleDiv.className = ""; //cart_crop_order_item_title
        titleDiv.innerHTML = this.retailerProductName;      
        
        titleDiv.appendChild(lowResImg);
        
        innerWrapperDiv.appendChild(titleDiv);                
        this.wrapperDiv.appendChild(innerWrapperDiv);
        
        return this.wrapperDiv;
        
    },  
    
    renderCropOverlay: function() {
        if (typeof(this.cropArea) == 'undefined' || this.cropArea == null)
        {
            this.cropArea = new CropArea();
        }        
        var imgdiv = $get(this.imageDivId);   
        this.cropArea.show(this.imageDivId, this.newCrop.left * imgdiv.width, this.newCrop.top * imgdiv.height, this.newCrop.right * imgdiv.width, this.newCrop.bottom * imgdiv.height);
    }
};

// Construct function for OrderItemPanel class.
function CropOrderItemPanel(icropEditor) {
    this.cropEditor = icropEditor;
}

CropOrderItemPanel.prototype = {

    panelContainerID: 'OrderItem_list',
    cropOrderItemArray: [],
    selectedCropOrderItemArrayPosition: null,
    cropEditor: null,

    addCropOrderItemBySubOrderItem: function(subOrderItem, orderItemCropWrapper)
    {
        this.addNewCropOrderItem(this, subOrderItem, orderItemCropWrapper, this.cropOrderItemArray.length);
    },

    clearUI: function()
    {

        var cell = $get(this.panelContainerID);

        if (cell.hasChildNodes())
        {
            while (cell.childNodes.length >= 1)
            {
                cell.removeChild(cell.firstChild);
            }
        }
    },

    clear: function()
    {
        this.cropOrderItemArray = new Array();
        this.selectedCropOrderItemId = null;
        this.selectedCropOrderItemArrayPosition = 0;
    },

    ImagesRenderCompleted: function()
    {
        if (this.cropOrderItemArray.length > 0)
        {
            for (i = 0; i < this.cropOrderItemArray.length; i++)
            {
                if (!this.cropOrderItemArray[i].ImagesRenderCompleted())
                {
                    return false;
                }
            }
            return true;
        }
        return false;
    },

    render: function(selectedRpID)
    {
        this.clearUI();

        var div = document.createElement("div");
        var table = document.createElement("table");
        var tableBody = document.createElement("tbody");
        table.appendChild(tableBody);
        var tr = document.createElement("tr");

        for (i = 0; i < this.cropOrderItemArray.length; i++)
        {
            var td = document.createElement("td");
            td.style.width = "124px";
            td.style.height = "140px";
            td.appendChild(this.cropOrderItemArray[i].render());
            tr.appendChild(td);
            tableBody.appendChild(tr);
        }

        div.appendChild(table);
        div = this.crossBrowserRenderingAdjustment(div);
        $get(this.panelContainerID).appendChild(div);
        this.selectedCropOrderItemArrayPosition = this.getCurrentSelectedPosition(selectedRpID);
        this.cropOrderItemArray[this.selectedCropOrderItemArrayPosition].setToSelected();
    },

    getCurrentSelectedPosition: function(selectedRpID)
    {
        for (i = 0; i < this.cropOrderItemArray.length; i++)
        {
            if (this.cropOrderItemArray[i].orderItem.EncRetailerProductID == selectedRpID) return i;
        }
        if (this.cropOrderItemArray.length > 0) return 0; //default selected one is the first entry
        return -1;
    },

    crossBrowserRenderingAdjustment: function(div)
    {
        if (this.browserIsFirefox())
        {
            div.style.position = 'fixed';
            div.style.overflow = 'hidden';
            div.style.width = '540px';
            div.style.overflow = "auto";
            div.style.overflowY = 'hidden';
        }
        if (this.browserIsIE7())
        {
            div.style.height = '160px';
            div.style.width = (138 * this.cropOrderItemArray.length) + 'px';
            div.style.overflow = 'hidden';
        }
        return div;
    },

    renderCropOverlay: function()
    {
        for (i = 0; i < this.cropOrderItemArray.length; i++)
        {
            this.cropOrderItemArray[i].renderCropOverlay();
        }
    },

    updateSelectedCropOrderItemId: function(id)
    {
        selectedCropOrderItemId = id;
    },

    addNewCropOrderItem: function(panel, subOrderItem, orderItemCropWrapper, position)
    {
        var cropOrderItem = new CropOrderItem(panel, subOrderItem, orderItemCropWrapper, position);
        Array.add(this.cropOrderItemArray, cropOrderItem);
        return true;
    },

    itemSelected: function(position) //////////////
    {
        var oiSelected = this.cropOrderItemArray[position];
        if (oiSelected.cropArea == null) {
            oiSelected.renderCropOverlay();
        }
        var cropInfo = oiSelected.cropArea;
        
        this.selectedCropOrderItemArrayPosition = position;
        this.clearAllSelected();
        this.cropOrderItemArray[position].setToSelected();
        this.cropEditor.newOrderItemSelected();

        //enter crop mode when switching to a new image
        if (this.cropOrderItemArray[position].orderItem.WarnCrop)
            this.cropEditor.changeCrop();

        //activate the appropriate landscape/potrait radio button
        if (cropInfo.cropWidth > cropInfo.cropHeight)
            $get(this.cropEditor.cropEditorEditPanel.landscapeRadioId).checked = true;
        else
            $get(this.cropEditor.cropEditorEditPanel.portraitRadioId).checked = true;
    },

    clearAllSelected: function()
    {
        for (i = 0; i < this.cropOrderItemArray.length; i++)
        {
            this.cropOrderItemArray[i].setToUnSelected();
        }
    },

    getCurrentCropOrderItem: function()
    {
        return this.cropOrderItemArray[this.selectedCropOrderItemArrayPosition];
    },

    getOrderItemCropWrappers: function()
    {
        var returnWrapperArray = new Array();
        for (i = 0; i < this.cropOrderItemArray.length; i++)
        {
            Array.add(returnWrapperArray, this.cropOrderItemArray[i].getOrderItemCropWrapper());
        }
        return returnWrapperArray;
    },

    getCartItemByRPId: function(rpId)
    {
        for (i = 0; i < this.cropOrderItemArray.length; i++)
        {
            if (this.cropOrderItemArray[i].orderItem.EncRetailerProductID == rpId)
            {
                return this.cropOrderItemArray[i];
            }
        }
        return null;
    },

    browserIsFirefox: function()
    {
        return (navigator.userAgent.indexOf("Firefox") != -1);
    },

    browserIsIE7: function()
    {
        var agent = navigator.userAgent.toLowerCase();
        var is_ie = ((agent.indexOf("msie") != -1) && (agent.indexOf("opera") == -1));
        var is_ie7 = (is_ie && agent.indexOf("msie 7.0") != -1);
        return is_ie7;
    }
};
function CropEditorEditPanel(icropEditor) {
    this.cropEditor = icropEditor;
}

CropEditorEditPanel.prototype = {
    // Configuration
    resWarnContainerId: 'ResolutionWarning',
    landscapeRadioId: 'rbLandscape',
    portraitRadioId: 'rbPortrait',
    currentCropCartItemId: null,
    cropper: null,
    cropArea: null,
    
    hasMinSize: true, //for low resolution detection
    cropOrientation: 'landscape',
    imageMainDivID: 'baseCropImage',
    rpid: null,
    currentAspectRatio: null,
    mediaID: '',
    cropping: false,
    cropLeft:0,
    cropTop:0,
    cropRight:0,
    cropBottom:0,
    cropOrderItem:null,
    minWidth:0,
    minHeight:0,
    loadOrigCropFlag: true, // a flag to indicate to load the original crop information to the page.
    editCropModeFlag: true, // a flag to indicate which mode it is in.
    currentOrderItem: null,
    isLowRes: false,
    minSizeMet: false,
    
    hideLowResDetection: function()
    {
        $get(this.resWarnContainerId).style.visibility = 'hidden';
    },
    
    loadCropCoords: function(source)
    {
        this.cropTop = source.top;
        this.cropLeft = source.left;
        this.cropRight = source.right;
        this.cropBottom = source.bottom;    
    },
    
    render: function(cropOrderItem)
    {   
        this.currentOrderItem = cropOrderItem;       
        this.rpid = cropOrderItem.getRPId();
        this.mediaID = cropOrderItem.eOrderItemMediaId;
        this.cropOrderItem = cropOrderItem;
        this.currentAspectRatio = cropOrderItem.aspectRatio;      
        this.minSizeMet = false;          
        
        if (this.loadOrigCropFlag)
        {            
            if (this.cropOrderItem.cropIsLandscape)
            {
                this.loadCropCoords(cropOrderItem.originalLandscapeCrop);
                this.setCropOrientation('rbLandscape', 'landscape');               
            }
            else
            {
                this.loadCropCoords(cropOrderItem.originalPortraitCrop);
                this.setCropOrientation('rbPortrait', 'portrait');                
            }
        }
        else if (!this.editCropModeFlag) //Load new coordinate.
        {
            this.loadCropCoords(cropOrderItem.newCrop);
            
            if (cropOrderItem.cropIsLandscape)
            {
                this.setCropOrientationNoReload('rbLandscape', 'landscape');                
            }
            else
            {
                this.setCropOrientationNoReload('rbPortrait', 'portrait');                
            }
        }
        
        this.enableApplyCrop(this.editCropModeFlag);
        this.enableStartOver(true);        
        
        var baseImage = new Image();
        baseImage.src = cropOrderItem.largeImageUrl;
        $get(this.imageMainDivID).src = cropOrderItem.largeImageUrl;
        
        if (this.editCropModeFlag)
        {
            this.startCropper();            
        }
        else
        {
            this.showCroppedArea();   
        }
        this.ShowResolutionWarning(cropOrderItem.isLowRes);
    },
    
    setIsLowRes: function(boolValue)
    {
        this.isLowRes = boolValue;
    },
    
    currentOrientation: function()
    {
        var landRadioBtn = $get(this.landscapeRadioId);
        if (landRadioBtn == null)
        {
            return 'landscape';
        }
        else
        {
            if (landRadioBtn.checked)
                return 'landscape';
            else
                return 'portrait';
        }        
        return null;
    },
    
    renderCropOverlay: function()
    {
        this.startCropper();
    },
    
    clearUI: function()
    {
        $get(this.imageMainDivID).src = '../images/spacer.gif';
        this.resetCropper(this.cropOrientation);
        this.enableOrientation(true);
        this.enableApplyCrop(true);
        this.editCropModeFlag = true;
        this.loadOrigCropFlag = true;
        this.hideCroppedArea();
        this.hideLowResDetection();
    },
    
    updateImage: function(cropOrderItem) {
        this.enableApplyCrop(true);
        this.editCropModeFlag = false;
        this.loadOrigCropFlag = false;
        this.render(cropOrderItem);
        //this.showCroppedArea();
    },
    
    clear:function(){
    },
    
    saveEdit: function()
    {
        this.cropOrderItem.newCrop.top = this.cropTop;
        this.cropOrderItem.newCrop.left = this.cropLeft;
        this.cropOrderItem.newCrop.right = this.cropRight;
        this.cropOrderItem.newCrop.bottom = this.cropBottom;
        this.cropOrderItem.cropSaved = true;
        this.cropOrderItem.renderCropOverlay();
        this.loadOrigCropFlag = false;
        this.editCropModeFlag = false;
        this.enableApplyCrop(false);
        this.enableStartOver(true);
        this.enableOrientation(false);
        this.showCroppedArea();
        this.saveIsLowRes(this.isLowRes);
    },
    
    saveIsLowRes: function (isLowRes)
    {
        if (!isLowRes) 
        {
            this.cropOrderItem.setIsLowRes(isLowRes);
        }
        else if (this.minSizeMet)
        {   
            this.cropOrderItem.setIsLowRes(false);
        }
    },
    
    enableOrientation: function(enable)
    {
        $get(this.landscapeRadioId).disabled = !enable;
        $get(this.portraitRadioId).disabled = !enable;    //imgPortrait
        if (enable)
        {
           $get("imgPortrait").onclick = function () { cropEditor.setCropOrientation('rbPortrait', 'portrait'); };
           $get("imgLandscape").onclick = function () { cropEditor.setCropOrientation('rbLandscape', 'landscape'); };
        }
        else
        {
            $get("imgPortrait").onclick = "";
           $get("imgLandscape").onclick = "";
        }
    },
    
    startOver: function()
    {
        this.loadCropCoords(this.cropOrderItem.startCrop);
        this.cropOrderItem.cropSaved = false;
        this.loadOrigCropFlag = true;
        this.render(this.cropOrderItem);        
        this.enableOrientation(true);
    },    
    
    changeCrop: function()
    {
        this.loadOrigCropFlag = false;
        this.editCropModeFlag = true;
        this.enableOrientation(true);
        this.render(this.cropOrderItem);    
    },    
    
    ImagesRenderCompleted: function() {
         var img = $get(this.imageMainDivID);
         var width = img.width;
         if ((width > 0) && (img.complete)) 
         {
            return true;
         }
         return false;
    },
    
    submitEdit: function() {
        //this.parent.submitEdits(); and parent will gather all edits from cartItemPanel and use the proxy to submit all edits
    },
    
    showCroppedArea: function()
    {        
        if (typeof(this.cropArea) == 'undefined' || this.cropArea == null)
        {
            this.cropArea = new CropArea();
        }
        this.resetCropper(this.cropOrientation);
        
        var imgdiv = $get(this.imageMainDivID);
        
        this.cropArea.show(this.imageMainDivID, this.cropLeft * imgdiv.width, this.cropTop * imgdiv.height, this.cropRight * imgdiv.width, this.cropBottom * imgdiv.height);
    },
    
    hideCroppedArea: function()
    {
        if (typeof(this.cropArea) != 'undefined' && this.cropArea != null)
        {
            this.cropArea.hide();
        }
    },
    
    resetCropper: function(orientation)
    {
        this.hasMinSize = false;
        
        if (typeof(this.cropper) == 'undefined' || this.cropper == null)
        {
            this.cropper = new Cropper();
            this.cropper.editPanelRef = this;   // store pointer back to this
        }
        
        if (this.cropping)
        {
            this.cropper.stopCropping();
        }
        
        this.cropping = false;
        this.cropOrientation = orientation;
        
        if ($get(this.landscapeRadioId) && $get(this.portraitRadioId))
        {
            switch (this.cropOrientation) {
                case 'landscape': {
                    $get(this.landscapeRadioId).checked = true;
                    $get(this.portraitRadioId).checked = false;                
                    break;
                }
                case 'portrait': {
                    $get(this.landscapeRadioId).checked = false;
                    $get(this.portraitRadioId).checked = true;                                
                    break;
                }
            }    
        }
        var e = $get(this.resWarnContainerId);
        e.style.visibility = 'hidden';
    },
    
    startCropper: function()
    {        
        this.hideCroppedArea();
        
        this.resetCropper(this.cropOrientation);
        
        var imgdiv = $get(this.imageMainDivID);
        
        if ((imgdiv.width == 16) && (imgdiv.width == 16))
        {
            this.enableApplyCrop(false);    
        }
        else
        {        
            var width = imgdiv.width;
            var height = width * this.currentAspectRatio;
            
            if (this.cropOrientation == 'portrait')
            {
                height = imgdiv.height;
                width = height * this.currentAspectRatio;
            }
            
            var initialTop = this.cropTop * imgdiv.height;
            var initialLeft = this.cropLeft * imgdiv.width;
            var initialWidth = (this.cropRight - this.cropLeft) * imgdiv.width;
            var initialHeight = (this.cropBottom - this.cropTop) * imgdiv.height;
            var minWidth = initialWidth / 5;
            var minHeight = initialHeight / 5;
            
            window.editPanelRef = this;            
            //this.cropEditor.getMinimumResOrderItemMedia(this.mediaID, this.rpid, this.currentAspectRatio);
            this.cropping = true;
            this.adjustMinWidthHeight(this.currentOrientation());
            this.cropper.startCroppingEx(this.imageMainDivID, initialLeft, initialTop, initialWidth, initialHeight, width, height, minWidth, minHeight, this.onCartCropChanged);
        }
    },    
    
    
    enableApplyCrop: function(enable)
    {
        if ((applyCropBtn != null) && (changeCropBtn != null)) {
            var buttonOn = 'none';
            var buttonOff = 'inline';
            if (enable) {
                buttonOn = 'inline'
                buttonOff = 'none'
            }        
            applyCropBtn.style.display = buttonOn;
            changeCropBtn.style.display = buttonOff;
        }
    },

    enableStartOver: function(enable)
    {
        if ((startoverOnBtn  != null) && (startoverOffBtn != null)) {
            var buttonOn = 'none';
            var buttonOff = 'inline';
            if (enable) {
                buttonOn = 'inline'
                buttonOff = 'none'
            }     
            startoverOnBtn.style.display = buttonOn;
            startoverOffBtn.style.display = buttonOff;
        }
    },
    
    setCropOrientationNoReload: function(sRadioBtn, orientation)
    {
        var radioBtn = $get(sRadioBtn);
        if (radioBtn != null)
            radioBtn.checked = true;
        this.cropOrientation = orientation;
    },
    
    setCropOrientation: function(sRadioBtn, orientation)
    {
        this.setCropOrientationNoReload(sRadioBtn, orientation);
        
        if (orientation == 'landscape')
        {
            this.loadCropCoords(this.cropOrderItem.originalLandscapeCrop);
        }
        else
        {
            this.loadCropCoords(this.cropOrderItem.originalPortraitCrop);
        }
        this.adjustMinWidthHeight(orientation);
    },
    
    adjustMinWidthHeight: function(orientation) 
    {        
        var imgdiv = document.getElementById(this.imageMainDivID)
        if (imgdiv.clientWidth == 1)
        {
            window.editPanelRef = this;
            setTimeout("this.editPanelRef.adjustMinWidthHeight('"+orientation+"');", 1000);
            return;
        }
        if (((orientation == 'landscape') && (this.currentOrderItem.isLandscape)) ||
            ((orientation != 'landscape') && (!this.currentOrderItem.isLandscape)))
        {
            this.cropper.minWidth  = this.minWidth = Math.round((imgdiv.clientWidth  * this.currentOrderItem.minLengthOfWidth) + 0.5);
            this.cropper.minHeight = this.minHeight = Math.round((imgdiv.clientHeight * this.currentOrderItem.minLengthOfHeight) + 0.5);         
        }
        else
        {
            this.cropper.minWidth  = this.minWidth = Math.round((imgdiv.clientHeight * this.currentOrderItem.minLengthOfHeight) + 0.5);
            this.cropper.minHeight = this.minHeight = Math.round((imgdiv.clientWidth  * this.currentOrderItem.minLengthOfWidth) + 0.5);       
        }
    },
    
    onCartCropChanged: function(cropInfo)
    {
        //
        // This function is running in the Cropper scope/frame/context, use this.editPanelRef to access 'this' edit panel...
        //
        
        var imgdiv = $get(this.editPanelRef.imageMainDivID);
        
        var l = eval(cropInfo.left) / imgdiv.clientWidth;
        if (l<0) l = 0;
        var r = eval((cropInfo.left) + cropInfo.width) / imgdiv.clientWidth;
        if (r > 0.99) r = 1.0;
        var t = eval(cropInfo.top) / imgdiv.clientHeight;
        if (t<0) t = 0;
        var b = eval((cropInfo.top) + cropInfo.height) / imgdiv.clientHeight;
        if (b > 0.99) b = 1.0;
        
        this.editPanelRef.cropLeft = l;
        this.editPanelRef.cropTop = t;
        this.editPanelRef.cropRight = r;
        this.editPanelRef.cropBottom = b;
        
//        if (this.editPanelRef.hasMinSize)
//        {
           this.editPanelRef.ShowResolutionWarning((cropInfo.width <= this.editPanelRef.minWidth) || (cropInfo.height <= this.editPanelRef.minHeight), (cropInfo.width == this.editPanelRef.minWidth) || (cropInfo.height == this.editPanelRef.minHeight));
//        }
    },
    
//    resetMinSize: function(cropOrderItem)
//    {
//         this.cropper.minWidth = this.minWidth = cropOrderItem.minLengthOfWidth;
//         this.cropper.minHeight = this.minHeight = cropOrderItem.minLengthOfHeight;
//    },
    
    onCropGotMinSize: function(result)
    {            
        var imgdiv = document.getElementById(this.imageMainDivID);
        this.cropper.minWidth  = this.minWidth  = Math.round((imgdiv.clientWidth  * result[0]) + 0.5);
        this.cropper.minHeight = this.minHeight = Math.round((imgdiv.clientHeight * result[1]) + 0.5);
        this.hasMinSize = true;
    },
    
    ShowResolutionWarning: function(result, minSizeMet)
    {        
        var visibleValue = 'hidden';
        if (result) visibleValue = 'visible';        
        $get('ResolutionWarning').style.visibility = visibleValue;
        this.setIsLowRes(result);
        this.minSizeMet = minSizeMet;
    }
};

//Communicate with Cart Service.

function CropEditorProxy(icropEditor, iEditPhotoService) {
    this.cropEditor = icropEditor;
    this.editPhotoService = iEditPhotoService;
}

CropEditorProxy.prototype = {
    cropEditor: null,
    editPhotoService : null,
    
    //Web service call and handler pairs.
    
    getOrderItemCropWrappers: function(eOrderItemIds,maxThumbPhotoSize,maxPreviewPhotoSize){
        this.editPhotoService.GetOrderItemCropWrappers(eOrderItemIds, maxThumbPhotoSize, maxPreviewPhotoSize, this.getOrderItemCropWrappersComplete, OnError);
    },
    getOrderItemCropWrappersComplete: function(result) {
        this.cropEditor.populateCropAspectInfoComplete(result);
    },    
    
    
    saveOrderItemCrops: function(orderItemCropWrapperList) {
        this.editPhotoService.SaveCropDatas(orderItemCropWrapperList, this.saveOrderItemCropsComplete, OnError);
    },
    saveOrderItemCropsComplete: function(result) {
        if (result == false)
        {
            //alert('failed to save. Please wait 15 minutes and try again later.');
            //redirect("error.aspx");
        }
        this.cropEditor.saveOrderItemCropsComplete();
        //else can do a success msg popup anything.
    },
    
    
    getMinimumResOrderItemMedia: function (mediaID, rpid, currentAspectRatio) {
        this.editPhotoService.GetMinimumResOrderItemMedia(mediaID, rpid, currentAspectRatio, this.getMinimumResOrderItemMediaComplete, OnError);
    },
    getMinimumResOrderItemMediaComplete: function (result) {
        this.cropEditor.getMinimumResOrderItemMediaComplete(result);
    },
    
    
    clear: function() {
    }
};

function SequenceCommandExecutor() {   
    this.Waiting = false;
}

SequenceCommandExecutor.prototype = {

    CommandArray: [],
    Waiting: null,
    
    Add: function(command) {
        this.CommandArray.push(command);
        this.ExecuteCommand();
    },
    
    ExecuteCommand: function() {
        if ((!this.Waiting) && (!this.IsEmpty()))
        {           
            var newCommand = this.CommandArray.splice(0,1);
            this.Waiting = true;
            eval(newCommand[0]);
        }
    },
    
    CommandCompleted: function() {
        this.Waiting = false;
        this.ExecuteCommand();
    },
    
    IsEmpty: function() {
        return (this.CommandArray.length == 0);
    },
    
    Clear: function() {
        CommandArray = new Array();
    }
};

if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();