
ShopForm.prototype = new FormObject();

function ShopForm_initAll()
// Init all add-to-cart forms on page (identifiable as such because 
// name = ShopForm[0-9]+
{
    $('.ShopForm').each(function() { this.shopForm = new ShopForm(this.id) });
}

function NotifyForm_initAll()
{
    $('.notify-form').each(function() {
        var f = new FormObject();
        f.init(this.id);
        f.ajaxSubmitCallback = NotifyProductSubmitCallback;
        f.setupAjaxSubmit('.notify-button');
    });
}

function ShopForm(id, field_prefix)
// CONSTRUCTOR. 
// On initial load of form, ensure that colour picture is 
// appropriate for default selection.
{
    this.init(id);
    this.OPTION_FIELD_PREFIX = 'CartItem0_';
    this.QTY_FIELD_NAME = 'CartItemQ0';

    this.currency = currency ? currency : new CurrencyConverter();    
    this.loadPriceLevels();

    this.bindEverything();
    this.showCalculatedPrice();

    var pf = this.getFieldValue('CartItemFlags', false);
    if (pf==undefined)
        pf='';

    this.productFlags = pf;

    // Selected quantity must be *exactly* that quantity to use that line.
    this.qualifyOnlyAtLevel = false;    
 
    // quantity desired must be a multiple of a level. 
    this.restrictToDefinedQuantities = false; 

    if (this.productFlags.indexOf('P') > -1)
    {
        this.qualifyOnlyAtLevel = true;
        this.restrictToDefinedQuantities = true;
    } else if (this.productFlags.indexOf('p') > -1) {
        this.qualifyOnlyAtLevel = true;
    } 

    // collect options into an array so we can iterate through them.
    this.optionNames = 0;
    return this;
}

ShopForm.prototype.getAllOptionNames  = function () {
    if (this.optionNames && this.optionNames.length > 0)
        return this.optionNames;

    var that=this;
    this.optionNames = new Array();

    $('.product-option').each(function() {
        var n = this.name;
        if (n)
        {
            var words = n.split('_');   // get last word
            if (words && words.length)
                that.optionNames[words[ words.length -1 ]] =1; 
        }
    });

    return this.optionNames;
}


// read form widgets into an array of objects.
ShopForm.prototype.loadPriceLevels = function () {
    var qpp = this.getFieldValue("CartItemQtyPerPound");

    var levels = new Array();
    for (var i=0; i<14; i++)
    {
        var f = this.getField("pricelevel_" + i, false);
        if (f) {
            var w = f.value.split(";");
            var thislevel = {
                qty : w[0],
                price : w[1],
                byWeight : (qpp>0 && (w[0] >= qpp/2))
            };
            levels.push(thislevel);
        } 
    } 

    this.priceLevels = levels;

    return levels;
}


// return the zero-based index of the qualifying price level.
// return -1 if not found.
ShopForm.prototype.findPriceLevelIndex = function (qty) {
    if (!this.priceLevels)
        this.loadPriceLevels();

    if (!this.priceLevels)
    {
        alert("cannot find price levels");
        return -1;
    } 


    qty = (+qty);

    for (var i = this.priceLevels.length - 1; i>=0 ; i--)
    {
        var thispl = this.priceLevels[i];
        var levelQty = +(thispl.qty);

        if (this.qualifyOnlyAtLevel)
        {
            // if qualifyOnlyAtLevel is set we use only those price levels
            // that are exact divisors.
            if ( (levelQty > 0) && ( 0==(qty % levelQty)))
                return i;
        } else {
            if ( qty >= levelQty)
                return i;
        }
    } 
    return -1;
}


ShopForm.prototype.handleSubmit = function(evt) {
    var ok = true;
    var didAlert=false;

    this.allwidgets.removeClass('validate-fail');

    this.form.find('select').each(function() {
        if (this.selectedIndex < 0)
        {
            if (!didAlert)
                alert("Please ensure that you have\nmade selections for every colour, size,\nor hand option.");
            didAlert=true;    
            ok = false;

            $(this).addClass('validate-fail');
        } 
    });

    return ok;
}

ShopForm.prototype.calculateUnitPrice = function (qty, index) {
    if (index<0)
        return -1;

    var thisLevel = this.priceLevels[index];
    if (thisLevel.qty == qty)
        return thisLevel.price;
    
    var nextLevel = this.priceLevels[index+1];
    if (!nextLevel)
        return thisLevel.price;

    if (this.restrictToDefinedQuantities || this.qualifyOnlyAtLevel)
        return thisLevel.price;

    // INTERPOLOATE:
    // alert("calculate between " + thisLevel.qty + " and " + nextLevel.qty );

    // position: 0.000000..1 => .99999...
    var q0 = +(thisLevel.qty);
    var q1 = +(nextLevel.qty);
    var p0 = +(thisLevel.price);
    var p1 = +(nextLevel.price);

    if (q1==q0) return p0;  // avoid divide=by-zero.

    var scale = (qty - q0) / (q1 - q0);
    if ( scale<0 || scale>1)
    {
        alert("invalid scale: " + scale) 
        return p0;
    } 

    var pdiff = p0-p1;    // a positive number
    var finalprice = p1 + ( (1-scale) * pdiff);
    // we have to scale this to a multiple of 0.01 because shopping cart 
    // does that internally, and it should match.
    finalprice = finalprice.toFixed(2);

    if (finalprice < nextLevel.price || finalprice < 0)
    {
        //alert("invalid final price: " + finalprice); 
        return p0;
    }

    return finalprice;
}

ShopForm.prototype.validateQuantity = function(q) {

    if (isNaN(q) || (q < 0))
    {
        return -1;
    } 

    if (q==0)
        return q;

    var max1 = this.getFieldValue('CartItemMaxQuantity0');
    if (max1>-1 && (q > max1))
    {
        alert("Sorry, we only have " + max1 + " of these in stock.");
        return max1;
    } 
    
    var min1 = this.getFieldValue('CartItemMinQuantity0'); 
    if (min1>1)
    {
        if ( (q % min1) !=0)
        {
            var qlist = (min1) + ", " + (2*min1) + ", " + (3*min1) + ", " + (4*min1) + "...";

            alert("We sell these only in packages of " + min1 + ".\n\nPlease choose a quantity that is a multiple of " + min1 + 
                ",\nsuch as " + qlist);
            q = ( min1 * Math.ceil(q / min1) );
            if (q > max1 && (max1>0) )
                q = q - min1;
            return q;
        } 
    } 

    var qpp = this.getFieldValue("CartItemQtyPerPound");
    // if (qpp > 4)
    if (false)
    {
        var bagsize = Math.floor(qpp / 4);
        if (q > bagsize)
        {
            var rem = (q % bagsize);
            if (rem!=0)
            {
                alert("At quantities exceeding one quarter pound, we sell these only\nby weight.  This quantity will be adjusted to the nearest quarter pound;\nbut this count is an approximation only.");
                return bagsize * Math.round(  q/bagsize );
            } 
        } 
    } 

    if (this.qualifyOnlyAtLevel)
    {
    //    for (var i = this.priceLevels.length - 1; i>=0 ; i--)
    //    {   
    //        var pl = this.findPriceLevelIndex(q);
    //    } 
    }

    return q;
}

ShopForm.prototype.getSelectedOption = function (widgetName)  {
// returns a matching OPTION or INPUT[type=Radio] for this name, if it's checked.
    var elements = this.form[0].elements;
    for (var i=0; i < elements.length; i++)
    {
        var elem = elements[i];
        if (elem.name==widgetName)
        {
            if (elem.type=="radio" && elem.checked)
                return elem;
            else if (elem.type=="select-one") {
                if (elem.selectedIndex > -1)
                    return elem.options[elem.selectedIndex];
            } 
        } 
    }
    return null;     
}

ShopForm.prototype.calculateOptionPrices = function () {
    var onames = this.getAllOptionNames();
    var totalPrice = 0;

    for (var oname in this.optionNames)
    {
        var selectedWidget = this.getSelectedOption(this.OPTION_FIELD_PREFIX + oname);
        if (selectedWidget)
        {
            var price = $(selectedWidget).attr('data-price');
            totalPrice = (+totalPrice) + (+price);
        } else {
            // dontcare - it's probably empty.  console.log("did not find " + this.OPTION_FIELD_PREFIX + oname);
        } 
    } 
    return totalPrice;
}

ShopForm.prototype.showCalculatedPrice = function () {
//    if (console) console.log("beginning recalculate " + this.formid);

    var q = +( this.getFieldValue(this.QTY_FIELD_NAME) );

    var outEach = this.form.find('.out_eachprice');
    var outOpts = this.form.find('.out_options');
    var optsWrap = this.form.find('.out_options_wrapper');
    var outTotal = this.form.find('.out_totalprice');

    outEach.html('');
    outOpts.html('');
    outTotal.html('');

    try {
        var pl = this.findPriceLevelIndex(q);
        if (pl>=0)
        {
            var unitPrice = +(this.calculateUnitPrice(q, pl));
        
            this.form.find('.selected_price_level').removeClass('selected_price_level');
            var priceLevel = this.priceLevels[pl];
            if (priceLevel)
            {
                $('#' + this.formid + "_qrow" + (priceLevel.qty)).addClass('selected_price_level');
            }
            
            if (unitPrice <0.01)
                return void(0);

            var optionPrice = +(this.calculateOptionPrices());
            var optionTotal = (+q)*(+optionPrice);

            if ((optionTotal > 0.00) && (q>1)) 
            {
                var itemTotal = (+q)*(+unitPrice);
                outEach.html( q + ' x ' + this.currency.symbol + " " + unitPrice.toFixed(2) + "<br/>" + 
                    'item total ' +  this.currency.symbol + " " + itemTotal.toFixed(2)
                );
                outOpts.html( 
                    q + ' x ' +  this.currency.symbol + " " + optionPrice.toFixed(2) + '<br/>' +
                    ' total ' + " " + this.currency.symbol + " " + optionTotal.toFixed(2) 
                );
            } else {
                outEach.html( this.currency.symbol + " " + unitPrice.toFixed(2) );
                outOpts.html( this.currency.symbol + " " + optionPrice.toFixed(2));
            } 

            if (optionPrice > 0.00)
            {
                optsWrap.show('slow');
            } else {
                optsWrap.hide('slow');
            } 

            var totalPrice = q * ( unitPrice + optionPrice);
            outTotal.html( this.currency.symbol + " " + totalPrice.toFixed(2) );
        }
     } catch (ex) {
        alert("Pricing error: " + ex);
     }
}

ShopForm.prototype.getQuantity = function () {
    return +( this.getFieldValue(this.QTY_FIELD_NAME) );
}

ShopForm.prototype.setQuantity = function (n) {
    if (isNaN(n))
    { 
        this.getField(this.QTY_FIELD_NAME).value = this.getField(this.QTY_FIELD_NAME).defaultValue;
    } else if (n>0) {
        this.putFieldValue(this.QTY_FIELD_NAME, n);
        this.showCalculatedPrice();
    }
    $(this.getField(this.QTY_FIELD_NAME)).removeClass('virgin-field');
}

ShopForm.prototype.incrQuantity = function (sign) {
    var oldq = this.getQuantity();
    var n = +(sign);

    if (oldq>=2000)
        n=1000*n;
    else if (oldq>=200)
        n=100*n;
    else if (oldq >=20)
        n=10*n;

    this.setQuantity ( +(n) + oldq);
    this.fixQuantity();

    this.showCalculatedPrice();
}

ShopForm.prototype.handleFocus = function (evt) {
    var target = $( evt.target ? evt.target : evt );
    
    if (target.hasClass('virgin-field'))
    {
        target.removeClass('virgin-field');
        target.val('');
    } 
    
    return void(0);
}

ShopForm.prototype.fixQuantity = function () {
    var q0 = this.getQuantity();
    var qty = this.validateQuantity(q0);

    if (isNaN(qty) || (qty < 0))
    {
        target = this.getField(this.QTY_FIELD_NAME);
        this.setQuantity(target.defaultValue);
    } else if (q0 != qty) 
        this.setQuantity(qty);
    return qty;
}

ShopForm.prototype.handleChange = function (evt) {
    var target = evt.target ? evt.target : evt;
    var jt = $(target);

    if (target.name == this.QTY_FIELD_NAME)
    {
        this.fixQuantity();
        this.showCalculatedPrice();
    } else if ( jt.hasClass('product-option')) {
        return this.handleOptionChange(jt, evt.type);
    }
}

ShopForm.prototype.setColourIfNeutral = function (target, colour) {
    // already have a selection? do nothing.

    if (target.selectedIndex > -1)
        return null;

    for (var i=0; target.options[i]; i++)
    {
        if (target.options[i].value == colour)
        {
            target.selectedIndex = i;
            this.displayColour($(target))
            return null;
        }
    }
    return null;
}

ShopForm.prototype.handleOptionChange = function (jt, etype) {
    var me = this;
    var opt = this.getSelectedOptionWidget(jt[0]);
    if (! opt)
    {
        alert(jt.attr('name') + ' - cannot determine selected value');
             //' selected : ' + opt.value + ' price=' + $(opt).attr('data-price') );
    }

    if ((opt.value == 'Heqal') && (etype == 'click'))
    {
        var q = +(this.getQuantity());
        if (q<2)
        {
            alert("You've chosen to receive an equal number of \n" + 
                "left-handed and right-handed fans.  For this to be possible, \n" +
                "you'll need to buy at least two fans.\n");
        } 
    } 

    if (jt.hasClass('product-option-colour'))
    {
        var colour = this.displayColour(jt);

        this.form.find('.product-option-colour').each(function() {
            me.setColourIfNeutral(this, colour);    
        });
    } else if ( jt.hasClass('product-option-assembly')) {
        var relevant  = this.form.find('.optionwidget_hand,.optionwidget_layout');

        if (opt && (opt.value == 'Akit'))
        {
            relevant.slideUp('slow').find('input').attr('checked', false);
        } else {
            relevant.slideDown('slow');
        } 
    }

    this.showCalculatedPrice();

    return void(0);
}

ShopForm.prototype.getSelectedOptionWidget = function (target) {
// option: a name or a jq-object
    // this.form.find
    if (target.type=="radio")
    {
        for (var i=0; i< this.form[0].elements.length; i++)
        {
            var e = this.form[0].elements[i];
            if (e.name==target.name)
            {
                if (e.checked) 
                    return e;
            } 
        } 
    } else if (target.type=="select-one") {
        if (target.selectedIndex > -1)
        {
            return target.options[target.selectedIndex];
        } 
    } else {
        alert("cannot figure type of " + target.type);
    } 
    return null;
}

ShopForm.prototype.getColourLocation = function (colourCode) {
    var ch = colourCode.substr(0,1);
    switch (ch)
    {
        case 'f': 
        case 'F': return 'feather';
        case 'b': 
        case 'B': return 'boa';
    }     
    return 'feather'; 
}

ShopForm.prototype.displayColour = function(jqwidget) {
    var selector    = jqwidget[0];
    var image       = $('#' + selector.id + "_pic");

    if (selector && (selector.selectedIndex > -1))
    {
        var opt = selector.options[selector.selectedIndex];
        if (opt && opt.text && image)
        {
            listprefix = this.getColourLocation(opt.value);

            image.attr('src', "/pictures/colours/" + listprefix + "/" + fixColourName(opt.text) + ".jpg");

            //$('.' + widgetid + "_zoomlink").each(function() {
            //    this.title = opt.text;
            //    this.href = "/pictures/colours/" + listprefix + "/" + fixColourName(opt.text) + "-big.jpg";
            //}).fancybox({'overlayShow': true });
            
            $('.' + selector.id + "_zoomlink").attr('title', opt.text).attr(
                'href', "/pictures/colours/" + listprefix + "/" + fixColourName(opt.text) + "-big.jpg").fancybox(
                {'overlayShow': true });
            return opt.value;
        } 
    } 

    // none selected
    if (image)
            image.src="/pictures/colours/select-colour.jpg";
    return void(0);
}

function fixColourName(cname)
{
    var sp = cname.indexOf(" (");
    if (sp>0)
    {
        cname = cname.substr(0,sp);
    }

	while (cname.indexOf(" ") >= 0) 
	{
		cname = cname.replace(" ", "-");
	}
    return cname;
}

function zoomprodimage (baseid)
{
    var fred = window.open(
        "/shop/cat?cmd=image&amp;baseid=" + baseid, 
        'prodzoom', 
        'width=700,height=700,menubar=no,location=no,scrollbars=yes');
    fred.focus();
    return void(0);
}

function showColourByCode(ccode)
// 2008
{
    if (ccode)
    {
        popupLarge('/bin/colourview?cmd=zoom&colour=' + ccode);
    } else {
        alert("please select a colour - after selecting you may zoom in");
    } 
    return void(0);
}

function getSelectedColour(widgetid)
// 2008
{
    var widget = document.getElementById(widgetid);
    if (widget && (widget.selectedIndex>-1) )
    {
        var opt = widget.options[widget.selectedIndex];
        return opt ? opt.value : null;
    } 
    return null;
}

function NotifyProductSubmitCallback(tree) 
// this will be bound to any notify forms on the product text pages.
{
    var jqtree = $(tree);

    this.throbber.hide('fast');

    var status = jqtree.find('status').text();
    var message = jqtree.find('message').text();
    if (status == 'error')
    {
        $('#' + this.formid + '-message').html('<div class="error">' + message + '</div>');
    } else {
        $('#' + this.formid + '-message').addClass('bold').html(message);
        $('#' + this.formid + '-inner').hide('slow');
        this.allwidgets.attr('disabled', true);
    }
}

// email this product - really old ... 
var emailThisXMLRequest = null;

function hideAllSelectors(hidden)
{
    var selectors = document.getElementsByTagName("select");
    for (var jj=0; jj<selectors.length; jj++)
    {
        selectors[jj].style.display= hidden ? "none" : "";
    }
    return 0;
}

function closeEmailPopup()
{
    var statusDiv = document.getElementById("emailThisStatus");
    if (statusDiv)
    {
        statusDiv.style.display="none";
        statusDiv.innerHTML = "";
    }

    var pop = document.getElementById('emailThisPopup');
    if (pop)
        pop.style.display = "none";

    hideAllSelectors(false);
    emailThisXMLRequest = null;
    return void(0);
}

function showEmailPopup(baseid, imagepath, shortname)
{
    var popup = document.getElementById("emailThisPopup");
    if (!popup)
    {
        return -1;
    } 

    hideAllSelectors(true);

    popup.style.display = "";

    var body = document.getElementsByTagName('body')[0];
    if (body)
    {
        popup.style.left = (body.clientWidth - popup.clientWidth)/2;
        popup.style.top = document.body.scrollTop + 
         (body.clientHeight - popup.clientHeight)/2;
        // popup.style.zIndex = 200;
    } else {
        alert("no body");
    }
 
    var hdl = document.getElementById("emailThisPopupHeadline");
    if (hdl)
        hdl.innerHTML = shortname;

    var img = document.getElementById("emailThisPopupImage");
    if (img)
        img.src = imagepath;

    var form = document.getElementById('emailThisForm');
    if (form)
        form.elements["baseid"].value = baseid;

    return void(0);
}

function handleEmailThisResponse(foo)
{
 //    alert("this is " + this + " , foo is " + foo );
    var req = emailThisXMLRequest;  // how sad we have to use a global
    if (req.readyState!=4)
        return 0;

    if (req.status!=200)
    {
        alert("error - request returned status " + req.status);
        return 0;
    } 

    var resp = req.responseXML;
    // alert("response " + resp);
    var stat = emailThisExtractXMLNodeValue(resp, "status");
    var message = emailThisExtractXMLNodeValue(resp, "message");

    var statusDiv = document.getElementById("emailThisStatus");
    if (stat == "ok")
    {
        statusDiv.style.color = "#004000";
        window.setTimeout(closeEmailPopup, 1500);
    } else {
        statusDiv.style.color = "#800000";
    } 
    statusDiv.style.display = "";
    statusDiv.innerHTML = message;

    return void(0);
}

function emailThisExtractXMLNodeValue(tree, nodename)
{
    var nodelist = tree.getElementsByTagName(nodename);
    if (nodelist)
    {
        var node1 = nodelist[0];
        if (node1)
         return node1.firstChild.nodeValue;
    }
    return "";
}


function doEmailThisFormPost(form)
{
    var statusDiv = document.getElementById("emailThisStatus");

    var formContents = formElementsToString(form);

    statusDiv.style.color = "#000000";
    statusDiv.innerHTML = "Contacting server...";
    statusDiv.style.display = "";

    emailThisXMLRequest = createAjaxPostRequest("/bin/xmlprodinfo");
    emailThisXMLRequest.onreadystatechange = handleEmailThisResponse;
    emailThisXMLRequest.send(formContents);

    return void(0);
}

