// HPS product access API
// Copyrights 2010, Loco (Loohuis Consulting)
// requires Prototype

document.observe("dom:loaded", function() {
    if ($('productpane')) {
        productClient = new HPSProductClient($('productpane'));
    }
    if ($('cartcontainer') || $('cartupdate')) {
        cart = new IOShopCart();
    }
});

// product display client
var HPSProductClient = Class.create({
    // application data
    // target element for display
    pane: null,
    // AJAX API
    api: null,
    // cache category id
    cat: null,
    // track authentication
    authenticated: false,

    // application setup
    initialize: function(target)
    {
        this.pane = target;
        this.authenticated = this.pane.hasClassName('authenticated');
        this.api = new ProductAPI;
        if ($('cartthrobber')) {
            $('cartthrobber').show();
        }
        // support deep linking
        parts = window.location.pathname.split('/');
        if (parts[1] == 'zoeken') {
            $('throbber').show();
            var query = unescape(parts[2].strip());
            if (!query.blank()) { // do search query
                this.api.get({
                    mode: 'search',
                    parms: {
                        query: query
                    },
                    callback: this.displaySearch.bind(this)
                });
            }
            else { // show search form
                var tpl = new Template('<h1>Zoeken</h1><p><form id="searchform">Zoek naar <input type="text" name="query" value=""><input type="submit" value="zoek"></p>');
                this.pane.update(tpl.evaluate({}));
                $('searchform').observe('submit', this.submitSearch.bindAsEventListener(this));
                $('throbber').hide();
            }
        }
        // add configuration update triggers
        this.pane.select('#configurator select').each(function(s)
        {
            s.observe('change', function(e)
            {
                this.api.get({
                    mode: 'config',
                    parms: $('configurator').serialize(true),
                    callback: this.updateConfig.bind(this)
                });
                e.stop();
            }.bindAsEventListener(this));
        }, this);
        // order form submit handler
        $$('form.order').each(function(f) {f.observe('submit', this.addOrder.bindAsEventListener(this))}, this);
    },

    // add an article to the cart
    addOrder: function(e)
    {
        e.stop();
        new Ajax.Updater($('cartupdate'), '/cart.php', {
            parameters: e.element().serialize(),
            onCreate: function() {$('cartupdate').empty();$('cartthrobber').show()},
            onSuccess: function() {$('cartthrobber').hide();}
        });
    },

    // callback for account data display
    displayAccount: function(json)
    {
        $('throbber').show();
        this.pane.update();
        var tpl = new Template('<p>Site: http://#{url}<br>API key: #{resellerkey}</p>');
        this.pane.insert(tpl.evaluate(json));
        window.scrollTo(0, 0);
        $('throbber').hide();
    },

    // redirect search to rewritten URL
    submitSearch: function(e)
    {
        e.stop();
        window.location = '/zoeken/' + escape(e.element().query.value);
    },

    // display search results
    displaySearch: function(json)
    {
        parts = window.location.pathname.split('/');
        var query = unescape(parts[2].strip());
        var tpl = new Template('<p><form id="searchform">Zoek naar <input type="text" name="query" value="#{query}"><input type="submit" value="zoek"></p>');
        this.pane.update(tpl.evaluate({'query': query}));
        $('searchform').observe('submit', this.submitSearch.bindAsEventListener(this));
        var row = new Template('<li><h3><a href="/producten/#{cat}/#{pid}/#{urlname}" pid="#{pid}">#{brand} #{name}</a></h3><p>#{abstract}</p></li>');
        var thumbrow = new Template('<li><a href="/producten/#{cat}/#{pid}/#{urlname}" pid="#{pid}"><img src="#{thumb}" class="thumb"></a><h3><a href="/producten/#{cat}/#{pid}/#{urlname}" pid="#{pid}">#{brand} #{name}</a></h3><p>#{abstract}</p></li>');
        var imgrow = new Template('<li><a href="/producten/#{cat}/#{pid}/#{urlname}" pid="#{pid}"><img src="#{image}" class="thumb"></a><h3><a href="/producten/#{cat}/#{pid}/#{urlname}" pid="#{pid}">#{brand} #{name}</a></h3><p>#{abstract}</p></li>');
        var countheader = new Template('<h2>#{count} producten gevonden</h2>');
        var count1header = new Template('<h2>1 product gevonden</h2>');
        var list = new Element('ul', {'class': 'index'});
        if (json) {
            if (json.list.length == 1)
                this.pane.insert(count1header.evaluate({'count': json.list.length}));
            else
                this.pane.insert(countheader.evaluate({'count': json.list.length}));
            $A(json.list).each(function(f)
            {
                f.urlname = (f.brand + ' ' + f.name).replace(/[^A-Za-z0-9_.]+/g, '_');
                if (f.thumb)
                    list.insert(thumbrow.evaluate(f));
                else if (f.image)
                    list.insert(imgrow.evaluate(f));
                else
                    list.insert(row.evaluate(f));
            }, this);
            this.pane.insert(list);
        }
        else {
            this.pane.insert('<h2>Geen producten gevonden</h2>');
        }
        $('throbber').hide();
    },

    // update the configuration
    updateConfig: function(json)
    {
        $('throbber').show();
        json.components.each(function(part)
        {
            if (part.caid && $('mod_' + part.caid)) {
                $('mod_' + part.caid).update('&euro; ' + (part.diff >= 0 ? '+' : '') + part.diff.toFixed(2).toString().replace('.', ','));
            }
        });
        if ($('total')) {
            $('total').update('&euro; ' + json.total.toFixed(2).toString().replace('.', ','));
        }
        if ($('powertotal')) {
            $('powertotal').update(json.power.toFixed(0) + 'W');
        }
        $('throbber').hide();
    },

    // utility functions

    // generate select with options, set selected if provided
    // properties are select element attributes
    // options is an object containing option values and output
    // selected is the selected value
    htmlOptions: function(properties, options, selected)
    {
        var select = new Element('select', properties);
        if (typeof options == 'object') {
            $H(options).each(function(o)
            {
                if (o.key == selected) {
                    select.insert(new Element('option', {'value': o.key, 'selected': 'selected'}).update(o.value));
                }
                else {
                    select.insert(new Element('option', {'value': o.key}).update(o.value));
                }
            });
        }
        return select;
    }
});

// shopping cart client
var IOShopCart = Class.create({
    // application setup
    initialize: function(target)
    {
        // cart status update at page load
        if ($('cartupdate')) {
            new Ajax.Updater('cartupdate', '/cart.php', {
                parameters: {status: 1},
                onCreate: function() {$('cartthrobber').show()},
                onSuccess: function() {$('cartthrobber').hide();}
            });
        }
        // cart display handler
        if ($('cartcontainer'))
            this.showCart();
    },

    // display the cart
    showCart: function()
    {
        new Ajax.Updater('cartcontainer', '/cart.php', {
            onCreate: function() {$('throbber').show()},
            onComplete: function(r)
            {
                $$('.cartlink').each(function(f) {f.observe('click', this.showCart.bindAsEventListener(this))}, this);
                $$('.recalc').each(function(f) {f.observe('click', this.recalculateCart.bindAsEventListener(this))}, this);
                $$('.address').each(function(f) {f.observe('click', this.showAddress.bindAsEventListener(this))}, this);
                $('throbber').hide();
            }.bind(this)
        });
        // track event with analytics
        if (_gaq)
            _gaq.push(['_trackEvent', 'order', 'cart']);
    },

    // recalculate the cart
    recalculateCart: function(e)
    {
        e.stop();
        var f = e.element().up('form');
        var parms = 'recalc=1&' + f.serialize();
        var del = e.element().getAttribute('order');
        if (del)
            parms += '&delorder=' + del;
        new Ajax.Updater($('cartcontainer'), '/cart.php', {
            parameters: parms,
            onCreate: function() {$('throbber').show()},
            onComplete: function()
            {
                $$('.cartlink').each(function(f) {f.observe('click', this.showCart.bindAsEventListener(this))}, this);
                $$('.recalc').each(function(f) {f.observe('click', this.recalculateCart.bindAsEventListener(this))}, this);
                $$('.address').each(function(f) {f.observe('click', this.showAddress.bindAsEventListener(this))}, this);
                $('throbber').hide();
            }.bind(this)
        });
        // track event with analytics
        if (_gaq)
            _gaq.push(['_trackEvent', 'order', 'cart']);
    },

    // show address form
    showAddress: function(e)
    {
        e.stop();
        new Ajax.Updater($('cartcontainer'), '/cart.php', {
            parameters: 'address=1',
            onCreate: function() {$('throbber').show()},
            onComplete: function()
            {
                $$('.cartlink').each(function(f) {f.observe('click', this.showCart.bindAsEventListener(this))}, this);
                $$('.address').each(function(f) {f.observe('click', this.showAddress.bindAsEventListener(this))}, this);
                $$('.payment').each(function(f) {f.observe('click', this.showPayment.bindAsEventListener(this))}, this);
                $('throbber').hide();
            }.bind(this)
        });
        // track event with analytics
        if (_gaq)
            _gaq.push(['_trackEvent', 'order', 'address']);
    },

    // show remarks form
    showPayment: function(e)
    {
        e.stop();
        var f = e.element().up('form');
        var parms = 'payment=1';
        if (f) {
            // validate form
            // check mandatory elements
            var fields = f.select('.mandatory');
            var incomplete = false;
            fields.each(function(i)
            {
                if (i.down('input').value.length == 0) {
                    incomplete = true;
                    i.addClassName('missing');
                }
                else
                    i.removeClassName('missing');
            });
            if (incomplete) {
                f.select('.validateerror').each(function(p) {p.show()});
            }
            else {
                parms += '&' + f.serialize();
                new Ajax.Updater($('cartcontainer'), '/cart.php', {
                    parameters: parms,
                    onCreate: function() {$('throbber').show()},
                    onComplete: function()
                    {
                        $$('.cartlink').each(function(f) {f.observe('click', this.showCart.bindAsEventListener(this))}, this);
                        $$('.address').each(function(f) {f.observe('click', this.showAddress.bindAsEventListener(this))}, this);
                        $$('.payment').each(function(f) {f.observe('click', this.showPayment.bindAsEventListener(this))}, this);
                        $$('.remarks').each(function(f) {f.observe('click', this.showRemarks.bindAsEventListener(this))}, this);
                        $('throbber').hide();
                    }.bind(this)
                });
            }
        }
        else {
            new Ajax.Updater($('cartcontainer'), '/cart.php', {
                parameters: parms,
                onCreate: function() {$('throbber').show()},
                onComplete: function()
                {
                    $$('.cartlink').each(function(f) {f.observe('click', this.showCart.bindAsEventListener(this))}, this);
                    $$('.address').each(function(f) {f.observe('click', this.showAddress.bindAsEventListener(this))}, this);
                    $$('.payment').each(function(f) {f.observe('click', this.showPayment.bindAsEventListener(this))}, this);
                    $$('.remarks').each(function(f) {f.observe('click', this.showRemarks.bindAsEventListener(this))}, this);
                    $('throbber').hide();
                }.bind(this)
            });
        }
        // track event with analytics
        if (_gaq)
            _gaq.push(['_trackEvent', 'order', 'payment']);
    },

    // show remarks form
    showRemarks: function(e)
    {
        e.stop();
        var f = e.element().up('form');
        var parms = 'remarks=1';
        if (f) {
            // validate form
            parms += '&' + f.serialize();
        }
        new Ajax.Updater($('cartcontainer'), '/cart.php', {
            parameters: parms,
            onCreate: function() {$('throbber').show()},
            onComplete: function()
            {
                $$('.cartlink').each(function(f) {f.observe('click', this.showCart.bindAsEventListener(this))}, this);
                $$('.address').each(function(f) {f.observe('click', this.showAddress.bindAsEventListener(this))}, this);
                $$('.payment').each(function(f) {f.observe('click', this.showPayment.bindAsEventListener(this))}, this);
                $$('.remarks').each(function(f) {f.observe('click', this.showRemarks.bindAsEventListener(this))}, this);
                $$('.complete').each(function(f) {f.observe('click', this.showComplete.bindAsEventListener(this))}, this);
                $('throbber').hide();
            }.bind(this)
        });
        // track event with analytics
        if (_gaq)
            _gaq.push(['_trackEvent', 'order', 'remarks']);
    },

    // show final order form
    showComplete: function(e)
    {
        e.stop();
        var f = e.element().up('form');
        var parms = 'complete=1';
        if (f) {
            // validate form
            parms += '&' + f.serialize();
        }
        new Ajax.Updater($('cartcontainer'), '/cart.php', {
            parameters: parms,
            onCreate: function() {$('throbber').show()},
            onComplete: function()
            {
                $$('.cartlink').each(function(f) {f.observe('click', this.showCart.bindAsEventListener(this))}, this);
                $$('.address').each(function(f) {f.observe('click', this.showAddress.bindAsEventListener(this))}, this);
                $$('.payment').each(function(f) {f.observe('click', this.showPayment.bindAsEventListener(this))}, this);
                $$('.remarks').each(function(f) {f.observe('click', this.showRemarks.bindAsEventListener(this))}, this);
                $$('.complete').each(function(f) {f.observe('click', this.showComplete.bindAsEventListener(this))}, this);
                $$('.checkout').each(function(f) {f.observe('click', this.checkout.bindAsEventListener(this))}, this);
                $('throbber').hide();
            }.bind(this)
        });
        // track event with analytics
        if (_gaq)
            _gaq.push(['_trackEvent', 'order', 'complete']);
    },

    // handle checkout
    checkout: function(e)
    {
        e.stop();
        var f = e.element().up('form');
        var parms = 'checkout=1';
        new Ajax.Updater($('cartcontainer'), '/cart.php', {
            parameters: parms,
            onCreate: function() {$('throbber').show()},
            onComplete: function() {$('throbber').hide()}
        });
        // track event with analytics
        if (_gaq)
            _gaq.push(['_trackEvent', 'order', 'checkout']);
    }
});


// extend Number class
Number.prototype.formatMoney = function(c, d, t)
{
    var n = this;
    c = isNaN(c = Math.abs(c)) ? 2 : c;
    d = d == undefined ? "," : d;
    t = t == undefined ? "." : t;
    var s = n < 0 ? "-" : "";
    var i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + ""
    var j = (j = i.length) > 3 ? j % 3 : 0;
    return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
};

