$.ajaxSetup ({
    // Disable caching of AJAX responses
    cache: false
});

var app = {
    
    URL: {

        host: 'http://katehillflowers.com.au',
        path: ''

    /*
        host: 'http://katehillflowers.dev',
        path: ''

        */
    }

}


$(document).ready(function() {

    if($('.accordion').length) {

        $.each($('.accordion'), function() {

            $(this).myAccordion();

        });

    }


    if($('#khf-slider').length) {

        $('#khf-slider').tinycarousel({pager: false, interval: true, duration: 200});

    }

    
});


if($('.hide-n-show').length) {

    var $el = $('.hide-n-show');

    $('ul', this).each(function(key, el) {

        $el.find('li').addClass('item-child').hide();
        $el.find('li:first').show().addClass('item-header').removeClass('item-child').click(function() {

            $el.find('.item-child').hide();
            $el.find('.expanded').removeClass('expanded');
            $(this).addClass('expanded');
            $(this).siblings('li').show();

        });

    });


}

$.myAccordion = function(el, opts){

    // To avoid scope issues, use 'base' instead of 'this'
    // to reference this class from internal events and functions.
    var base = this;

    // Access to jQuery and DOM versions of element
    base.$el = $(el);
    base.el = el;


    // Add a reverse reference to the DOM object
    base.$el.data("myAccordion", base);

    base.init = function(){

        base.opts = $.extend({},$.myAccordion.defaultOptions, opts);

        base.reset();

        base.$el.children('li').prepend('<div class="toggle">&nbsp;</div>').addClass('first-child');

        base.initEventListeners();

        return base;
    };

    base.initEventListeners = function() {

        base.$el.children('li').click(function() {

            var $content = $(this).children('ul');

            $content.toggle();
            
            if($content.is(':visible')) {
                $(this).addClass('expanded');
            }
            else {
                $(this).removeClass('expanded');
            }


        });

    };

    base.reset = function() {

        $('.expanded').removeClass('expanded');
        $('li>ul', base.$el).hide();

    };

    // Run initializer
    base.init();
}

$.myAccordion.defaultOptions = {
};

$.fn.myAccordion = function(opts){
    return new $.myAccordion(this, opts);
};




var AddToCart = {

    init: function(el, options) {

        this.options = $.extend({},this.options,options);
        this.el = el;
        this.$el = $(el);

        this.id = null;
        this.nextId = null;
        this.nextName = '';
        this.params = [];
        this.value = '';

        this.initEventListeners();

        return this;

    },


    initEventListeners: function() {

        $('.attribute-select').change(function() {

            AddToCart.setId($(this).attr('id').match(/[0-9]+/));

            AddToCart.setValue($(this).val());
            AddToCart.setNext(AddToCart.id);

            if(AddToCart.nextId != AddToCart.id) {
                AddToCart.reset();
                if(AddToCart.value) AddToCart.buildOptions();
            }
        });

        $('.addtocart').click(function() {

            if(AddToCart.validateForm()) {

                AddToCart.addItem();

            }

        });

    },

    options: {
        attributes: {}
    },


    addItem: function() {

        var ran = Math.floor(Math.random()*10000);

        $('#addtocart-response').html('<span class="icon-txt icon-loading">Adding..</span>');

        $.getJSON(app.URL.path+'/checkout/add?ran=' + ran, $('#addtocart-form').serialize(), function(j) {

            if(!j.error) {
                AddToCart.loadCart();
                $('#addtocart-response').html('<span class="icon-txt icon-tick">'+j.msg+'</span>');
            }
            else {
                $('#addtocart-response').html(j.msg);
            }

        });

    },


    buildOptions: function() {

        $('#attribute-select'+this.getNextId()).html('<option value="">Updating...</option>');

        this.setParams();

        $.getJSON(app.URL.path+'/options', {attributes: AddToCart.params, nextAttributeId: AddToCart.getNextId()}, function(j) {

            AddToCart.setDisabled(AddToCart.getNextId(), false);

            $('#attribute-select'+AddToCart.getNextId()).html('');

            $.each(j.options, function() {

                var text = this.value + (this.available ? '' : ' &#45; out of stock');
                var attrs = (this.available ? '' : ' disabled="disabled"');
                var option = '<option value="'+this.value+'"'+attrs+'>'+text+'</option>';

                $('#attribute-select'+AddToCart.getNextId()).append(option);

            });

        });

    },

    getNextId: function() {

        return this.nextId;
    },


    getNextName: function() {

        return this.nextName;
    },

    loadCart: function() {
        $.post(app.URL.path+'/checkout/panel?preview=true', function(j) {
            $('#cart').html(j);
        });
    },

    reset: function() {

        var found = false;

        return $.each(this.options.attributes, function(attributeId, attributeName) {

            if(found) {
                AddToCart.setDisabled(attributeId, true);
            }

            found = (AddToCart.id == attributeId) ? true : false;

        });

    },


    setDisabled: function(id, disable) {

        $('#attribute-select'+id).attr('disabled', (disable ? 'disabled' : '') );

    },

    setId: function(id) {

        this.id = id;
    },

    setNext: function(id) {

        var found = false;

        return $.each(this.options.attributes, function(attributeId, attributeName) {

            if(found) {
                AddToCart.nextId = attributeId;
                AddToCart.nextName = attributeName;
                return false;
            }

            found = (id == attributeId) ? true : false;

        });

    },

    setParams: function() {

        AddToCart.params = [];

        $.each(this.options.attributes, function(attributeId, attributeName) {

            var value = $('#attribute-select'+attributeId).val();

            if(value != '' && value != null) {
                AddToCart.params[AddToCart.params.length] = {id: attributeId, value: value};
            }

        });

    },

    setValue: function(value) {

        this.value = value;
    },

    validateForm: function() {

        var valid = true;

        $.each(this.options.attributes, function(attributeId, attributeName) {

            var value = $('#attribute-select'+attributeId).val();

            if(value == '' || value == null) {

                $('#addtocart-response').html('Please select a ' + attributeName.toLowerCase());

                valid = false;

            }

        });

        return valid;

    }

}


var ShoppingCart = {


    init: function(el, opts) {

        this.opts = $.extend({},this.opts,opts);
        this.el = el;
        this.$el = $(el);

        this.initEventListeners();

        return this;

    },


    initEventListeners: function() {

        $('.cart-item input:text').change(function() {

            if($(this).val().match(/[0-9]+/)) {

                var itemid = $(this).attr('id').match(/[0-9]+/);

                ShoppingCart.updateItemQuantity(itemid, $(this).val());

            }

        });

        $('.increment').click(function() {

            var itemid = $(this).attr('id').match(/[0-9]+/);
            ShoppingCart.updateItemQuantity(itemid, ShoppingCart.getItemQuantity(itemid)+1);
            return false;

        });

        $('.decrement').click(function() {

            var itemid = $(this).attr('id').match(/[0-9]+/);
            ShoppingCart.updateItemQuantity(itemid, ShoppingCart.getItemQuantity(itemid)-1);
            return false;

        });

        $('.remove-item').click(function() {

            var itemid = $(this).attr('id').match(/[0-9]+/);
            ShoppingCart.removeItem(itemid);

        });


    },

    opts: {},

    getItemPrice: function(itemid) {

        return ShoppingCart.opts.items[itemid].price;

    },

    getItemQuantity: function(itemid) {

        return ShoppingCart.opts.items[itemid].quantity;

    },

    getSubtotal: function() {

        var subtotal = 0;

        for(var item in this.opts.items) {

            subtotal += parseFloat(this.opts.items[item].price * this.opts.items[item].quantity);

        }

        return subtotal.toFixed(2);

    },


    updateItemQuantity: function(itemid, value) {

        if(value < 1) {

            ShoppingCart.removeItem(itemid);

        }
        else {

            // Set the quantity
            ShoppingCart.opts.items[itemid].quantity = parseInt(value);

            // Update everything else
            ShoppingCart.outputItemQuantity(itemid);
            ShoppingCart.outputItemPrice(itemid);
            ShoppingCart.outputPriceSummary();


        }

        return this;

    },


    outputItemQuantity: function(itemid) {

        $('#cart-item-quantity'+itemid).val(ShoppingCart.getItemQuantity(itemid));

    },

    outputItemPrice: function(itemid) {

        var linePrice = this.getItemQuantity(itemid) * this.getItemPrice(itemid);

        $('#cart-item-price'+itemid).html(linePrice.toFixed(2));

    },

    outputPriceSummary: function() {

        var subtotal      = this.getSubtotal();

        var taxrate       = parseFloat(this.opts.taxrate);
        var divisor       = parseFloat((taxrate)/100 + 1);
        var nettotal      = parseFloat(subtotal/divisor).toFixed(2);
        var tax           = parseFloat(subtotal - nettotal).toFixed(2);
        var shippingprice = parseFloat(this.opts.shippingprice).toFixed(2);


        var total = (parseFloat(subtotal) + parseFloat(shippingprice)).toFixed(2);

        $('#taxrate').html(taxrate);
        $('#cart-tax').html(tax);
        $('#cart-shipping').html(shippingprice);
        $('#cart-subtotal').html(subtotal);
        $('#cart-total').html(total);


        return this;

    },



    removeItem: function(itemid) {

        if(confirm('Are you sure you want to remove this item?')) {

            $.post(app.URL.path+'/checkout/delete?id='+itemid, function() {

                $('#cart-item'+itemid).fadeOut();
                delete ShoppingCart.opts.items[itemid];
                ShoppingCart.outputPriceSummary();

                var empty = true;

                for(var item in ShoppingCart.opts.items) {

                    empty = false;
                    break;

                }

                if(empty) {

                    $('#cart-is-empty').show();
                    $('#cart-is-not-empty').hide();

                }
                
            });

            return true;

        }
        else {

            return false;

        }

    }

}






var KhfCycle = {


    init: function(el, opts) {

        this.opts = $.extend({},this.opts,opts);
        this.el = el;
        this.$el = $(el);

        this.imageQueue = [];
        this.first      = true;
        this.timeout    = 3000;

        $.each(this.opts.images, function(key, filename) {

            var img = new Image();

            $(img).load(function() {

                var ind = KhfCycle.imageQueue.length;
                KhfCycle.imageQueue[ind] = filename;

                if(KhfCycle.first) {
                    KhfCycle.cycle(KhfCycle.opts.images[key+1], ind+1, KhfCycle.timeout); // +1 because we skip the first (already loaded with page)
                    KhfCycle.first = false;
                }

            }).error(function () {
              //alert(filename);  // File probably doesn't exist
            }).attr('src', filename);

        });

        return this;

    },

    cycle: function(filename, ind, timeout) {

        var $el = this.$el;
        
        setTimeout(function(){

            $el.css('background-image', "url("+filename+")").hide().fadeIn(1500);

            if(ind+1 <= KhfCycle.imageQueue.length) {

                var nextInd = ind+1;

                // Sometimes the image hasn't loaded yet, so start from beginning
                if(KhfCycle.imageQueue[nextInd] === undefined) {
                    nextInd = 0;
                }

            }
            else {

                var nextInd = 0;
            }

            KhfCycle.cycle(KhfCycle.imageQueue[nextInd], nextInd, KhfCycle.timeout);
            
        }, timeout);

    }

}



$.khfGallery = function(el, opts){

    var base = this;

    base.$el = $(el);
    base.el = el;

    base.$el.data("khfGallery", base);

    // Cached jquery elements
    var $stage = $('#khf-stage'),
        $stageElements = $stage.find('li'),
        $nav = $('#khf-nav'),
        $navElements = $nav.find('li'),
        $pager = $('.pager', base.el),
        $pagerElements = $('.pager li', base.el),
        $prev = $('#khf-prev'),
        $next = $('#khf-next');


    // Pseudo-private members
    var _index = 0,
        _clicked = false,
        _pagerLength = $pagerElements.length,
        _noOfPics = $stageElements.length+1,
        _noOfPages = Math.ceil(_noOfPics/8)+1,
        defaults = $.extend({},$.khfGallery.defaultOptions, opts);


    base.init = function(){

        $stage.css('width', defaults.previewwidth);
        $nav.css('width', defaults.navwidth);

        $stageElements.each(function(ind, el) {
            $(el).css('width', defaults.nodes[ind].width);
            $(el).css('height', defaults.nodes[ind].height);
        });

        base.initEventListeners();

        $navElements.animate( {opacity : 0.5} );
        $stageElements.animate( {opacity : 0.3} );
        $navElements.eq(0).animate( {opacity : 1} );
        $stageElements.eq(0).animate( {opacity : 1} ).find('.caption').animate( { bottom: 5 });
        base.disablePage(0);
        $prev.hide();
        $pagerElements.eq(1).addClass('active');
  
        return base;
        
    };


    base.initEventListeners = function() {

        $navElements.each(function(node, el) {
        
            base.preloadImage($(el), app.URL.path+'/images/gallery/s/'+defaults.nodes[node].filename);

        });

        $stageElements.add($navElements).click(function() {

            var newIndex = $(this).index();

            if(!_clicked && _index != newIndex) {

                _index = newIndex;

                base.slideToPreview(_index);

                
            }
            
        });

        $pagerElements.click(function() {

            var index = $(this).index();

            switch (index) {

                case 0:
                    base.paginateTo(base.getPage()-1);
                    break;

                case (_pagerLength-1):
                    base.paginateTo(base.getPage()+1);
                    break;

                default:
                    base.paginateTo(index);

            }

            return false;
            
        });


        $prev.click(function() {

            if(!_clicked) {

                _index--;
                base.slideToPreview(_index);


            }

        });


        $next.click(function() {

            if(!_clicked) {

                _index++;

                base.slideToPreview(_index);
                
            }
            
        });

    };

    base.enablePage = function(page) {
        $pagerElements.eq(page).children('a').css('visibility', 'visible');
    };

    base.disablePage = function(page) {
        $pagerElements.eq(page).children('a').css('visibility', 'hidden');
    };

    base.preloadImage = function($el, filepath) {

        var img = new Image();

        $(img).load(function () {
            $(this).css('display','none');
            $el.removeClass('loading').append(this);
            $(this).fadeIn();
        }).error(function () {
            $el.remove();
        }).attr('src', filepath);

    };

    base.getPage = function() {
        var activeItem = $('.active', $pager);
        return $pagerElements.index(activeItem);
    };

    base.getDistanceTo = function(node) {

        var xPosition = parseInt($stage.css('left').match(/[0-9]+/));
        var distance = (defaults.nodes[node].position - ((defaults.stagewidth/2) - (defaults.nodes[node].width)/2)) - xPosition;

        // When returning to first element, stops it from being centred
        if(defaults.nodes[node].position < (defaults.stagewidth/2 - (defaults.nodes[node].width)/2)) {
            distance = -xPosition;
        }

        return distance;

    };


    base.loadImages = function(index) {

        var nbEitherSide = 2;

        for(var i = (index - nbEitherSide); i <= (index + nbEitherSide); i++) {

            var $el = $stageElements.eq(i);
            
            if(i > -1 && i < (_noOfPics-1) && !$el.find('img').length) {
                
                $el.addClass('loading');
                base.preloadImage($el, app.URL.path+'/images/gallery/l/'+defaults.nodes[i].filename);
                
            }
            
        }

    };

    base.slide = function(container, distance, node) {

        container.stop().animate({
            left: '-=' + distance
        }, defaults.duration, defaults.easing, function() {

            if(node != undefined) {

                $stageElements.find('.caption').animate({ bottom: -40 });

                $stageElements.eq(node).fadeTo(200, 1, function() {
                    
                    $(this).find('.caption').animate({ bottom: 5 });

                    _index > 0 ? $prev.show() : $prev.hide();

                    _index < (_noOfPics-2) ? $next.show() : $next.hide();

                    var page = Math.ceil((_index+1)/8);

                    if(page > 0 && page <= _noOfPages) {
                         base.paginateTo(page);
                    }

                });
                
                $navElements.eq(node).fadeTo(200, 1);

            }
            
            _clicked = false;

        });

    };

    base.paginateTo = function(page) {

        base.enablePage(0);
        base.enablePage(_pagerLength-1);

        if(page <= 1) {

            base.disablePage(page-1);

        }
        else if(page > _noOfPages - 2) {

            base.disablePage(_pagerLength-1);

        }
        
        // Don't allow navigating around
        if(page < 1 || page > _pagerLength - 2) {
            return;
        }

        var position = $nav.css('left') !== undefined ? parseInt($nav.css('left').match(/[0-9]+/)) : 0;
        var distance = -(position - ((page-1) * defaults.stagewidth));

        $pagerElements.removeClass('active').eq(page).addClass('active');

        base.slide($nav, distance);

    };


    base.slideToPreview = function(index) {

        _clicked = true;
        $navElements.animate( { opacity : 0.3 } );
        $stageElements.animate( { opacity : 0.3 } );
        base.loadImages(index);
        base.slide($stage, base.getDistanceTo(index), index);

    };

    base.init();

}

$.khfGallery.defaultOptions = {
    easing: 'easeInOutQuart',
    duration: 500
};

$.fn.khfGallery = function(opts){
    return new $.khfGallery(this, opts);
};









$.filterBox = function(el, options){

    // To avoid scope issues, use 'base' instead of 'this'
    // to reference this class from internal events and functions.
    var base = this;

    // Access to jQuery and DOM versions of element
    base.$el = $(el);
    base.el = el;
    base.$filter = $('ul', base.el);

    // Add a reverse reference to the DOM object
    base.$el.data("filterBox", base);

    base.init = function(){

        base.options = $.extend({},$.filterBox.defaultOptions, options);

        base.initEventListeners();

        return base;
    };


    base.initEventListeners = function() {

        base.$el.click(function(event) {

            if(base.$filter.is(':hidden')) {
                base.$filter.show();
            }
            event.stopPropagation();

        })

        $('body').click(function() {

            base.$filter.hide();

        });

/*
        base.$filter.click(function() {

            var tag = $('a', this).html().toLowerCase();

            $('.cp').each(function() {

                if(!($(this).hasClass(tag))) {

                    $(this).animate( { width: 0 } );

                }
                else {

                    $(this).animate( { width: 180 } );
                }

            });

        });*/
    };

    // Run initializer
    base.init();
};

$.filterBox.defaultOptions = {
};

$.fn.filterBox = function(options){
    return new $.filterBox(this, options);
};






// categoryProduct
$.categoryProduct = function(el, options){

    // To avoid scope issues, use 'base' instead of 'this'
    // to reference this class from internal events and functions.
    var base = this;

    // Access to jQuery and DOM versions of element
    base.$el = $(el);
    base.el = el;

    // Add a reverse reference to the DOM object
    base.$el.data("categoryProduct", base);

    base.init = function(){

        base.options = $.extend({},$.categoryProduct.defaultOptions, options);

        base.initEventListeners();

        return base;
    };


    base.initEventListeners = function() {

        base.$el.click(function(event) {

            var id = $(this).attr('id').replace('cp', '');
            
            var filepath = $(this).find('img').attr('src').replace(/http:\/\/katehillflowers.com.au|"|^url|[\(\)]/g, '');

            filepath = filepath.replace(/\/m\//, '/l/');    // Change to large image

            // If the product is not already being previewed. Load the preview
            if(!$('#cp-hero' + id).length) {

                $(this).append('<div class="cp-loader"><img src="'+app.URL.path+'/images/ajax-loader.gif" /></div>');

                $.getJSON(app.URL.path+'/category/loadPreview', {pid: id, cid: 2}, function(j) {

                    $('#cp-hero').html(j.html);

                    var img = new Image();

                    $(img).load(function () {

                        $('#cp-hero'+id).fadeTo(600, 1, function() {

                            if($.browser.msie) {
                                this.style.removeAttribute("filter");// Fix for ie
                            }

                        });

                        $('.cp-loader').remove();
                        
                        $('.cp-preview a').html(this);

                    }).error(function () {
                            alert('hi');
                        $(img).remove();
                    }).attr('src', filepath).attr('height', j.height).attr('width', j.width);


                });
            }
            else {

                // If the product is already being previewed and they click it again. Send them to the product page
                window.location = app.URL.host+($('#cp'+id).find('a').attr('href'));

            }

        });

        base.$el.hover(function(){
                $('.cp-popup', this).stop().animate({bottom:'-15px'},{queue:false,duration:200});
        }, function() {
                $('.cp-popup', this).stop().animate({bottom: '-45px'},{queue:false,duration:200});
        });

        // Stop image changing
        $('.cp-popup').click(function(event){
            event.stopPropagation();
        });

    };

    // Run initializer
    base.init();
};

$.categoryProduct.defaultOptions = {
};

$.fn.categoryProduct = function(options){
    //return this.each(function(){
    return new $.categoryProduct(this, options);
   // });
};



// khfForm
$.khfForm = function(el, opts){

    var base = this;

    base.$el = $(el);
    base.el = el;

    // Add a reverse reference to the DOM object
    base.$el.data("khfForm", base);

    base.init = function(){

        base.opts = $.extend({},$.khfForm.defaultOptions, opts);

        base.globalError = false;

        base.initEventListeners();

        return base;
    };


    base.initEventListeners = function() {

        // Need to do this
        // Try filling out a field and pressing 'enter'
        base.initTipsy();

        
        base.$el.delegate('input[type=text], textarea', 'focusin', function() {

            base.onInputFocus(this);

        });


        base.$el.delegate('input[type=text], textarea', 'blur', function() {

            base.onInputBlur(this);

        });


        base.$el.submit(function() {

            return base.onFormSubmit();
            

        });

        var fields = base.opts.fields;

        for(var f in fields) {

            var id = fields[f].id;

            base.$el.delegate('#'+id, 'change', function() {
                
                base.validateField(this);

            });

        }

    };


    base.addError = function(field) {

        //var $el = $('#'+field.id);

        $('#error-'+field.id).remove();
        //$el.after('<label id="error-'+field.id+'" class="input-error" style="display: none"><span>'+field.messages[field.errortype]+'</span></label>');
        //$('#error-'+field.id).slideDown();

        var $el = $('#'+field.id);
        $el.attr('title', field.messages[field.errortype]);
        $el.tipsy({trigger: 'manual', gravity: base.opts.tipsyGravity, html: true}).tipsy('show');

    };

    base.removeError = function(field) {
        
        var $el = $('#'+field.id);
        field.errortype = null;
      //  $('#error-'+field.id).remove();
        $el.tipsy('hide');
        
    };

    base.renderErrors = function() {

        var fields  = base.opts.fields;
        var msg     = '';

        for(var f in fields) {

            var field = fields[f];

            if(field.errortype != undefined) {

                msg += '<li title="'+field.name+'">'+field.messages[field.errortype]+'</li>';

            }

        }
        
        msg = '<div class="box-error">There are few more bits of information we need:<br /><ul>'+msg+'</ul></div>';
        
        base.opts.hasOwnProperty('responseEl') ? base.$el.find(base.opts.responseEl).html(msg) : $('form-response').html(msg);

    };


    base.clearFields = function() {

        var fields = base.opts.fields;

        for(var f in fields) {

            base.$el.find('input[type=text]').val('');

            base.$el.find('select option:first-child').attr('selected', 'selected');

        }

    };

    base.onInputFocus = function(obj) {

        var $el = $(obj);

        $('.focused').removeClass('focused');

        $el.addClass('focused').siblings('label').addClass('focused');

        var field = base.opts.fields[$el.attr('id')];


    };

    base.onInputBlur = function(obj) {

        var $el = $(obj);

        var field = base.opts.fields[$el.attr('id')];


    };

    base.onFormSubmit = function() {

        base.validateForm();

        var error = base.globalError;

        if(!error && base.opts.hasOwnProperty('submitMethod') && base.opts.submitMethod.toLowerCase() === 'ajax') {
            base.submitViaAjax();
            return false;
        }

        return !error;

    };

    base.initTipsy = function() {

        var fields = base.opts.fields;

        for(var f in fields) {
            $('#'+fields[f].id).tipsy({trigger: 'manual', gravity: base.opts.tipsyGravity, html: true, fallback: fields[f].required});
        }

    };

    base.submitViaAjax = function() {

        var $responseEl = $(base.opts.responseElement);

        $responseEl.html('<span class="loading">Submitting</span>');

        $.getJSON(app.URL.path+base.opts.submitURL, base.$el.serialize(), function(j) {

            $responseEl.html(j.message);

            base.clearFields();

        });

    };


    base.validateField = function(elem) {

        var $elem       = $(elem);
        var id          = $elem.attr('id');
        var field       = base.opts.fields[id];


        if(field === undefined) {

            return;

        }


        var fieldValue  = $('#'+id).val();

        field.errortype = null;

        if(($elem).is(':visible')) {

            switch(field.type) {

                case 'email':

                    if(!fieldValue.match(/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i)) {

                        field.errortype = 'invalid';

                    }
                    break;

                case 'date':

                    if(!fieldValue.match(/^\d{1,2}\/\d{1,2}\/\d{4}/)) {

                        field.errortype = 'invalid';

                    }
                    break;

            }

            if(field.required && (!fieldValue.length || fieldValue === field.defaulvalue)) {

                field.errortype = 'required';

            }

        }


        if(field.errortype !== null) {

            base.addError(field);
            base.globalError = true;

        }
        else {

            base.removeError(field);

        }

    };

    base.validateForm = function() {

        var fields = base.opts.fields;
        
        base.globalError = false;

        for(var f in fields) {

            base.validateField($('#'+fields[f].id));

        }

        if(base.globalError) {

            base.renderErrors();

        }
            
        return base.globalError;

    };

    // Run initializer
    base.init();
    
};

$.khfForm.defaultOptions = {
    tipsyGravity: 'n'
};

$.fn.khfForm = function(opts){
    //return this.each(function(){
    return new $.khfForm(this, opts);
   // });
};

var OrderAddressForm = {

    init: function(elem, options) {

        this.options = $.extend({},this.options,options);
        this.el = elem;
        this.$el = $(elem);
        this.$billing = $('#billing-address');
        this.$shippingOptions = $('#shipping-options');

        this.form = this.$el.khfForm(this.options);

        this.initEventListeners();
        
        return this;

    },

    initEventListeners: function() {

        // Hide/show billing section
        $('#order_shiptobilling').change(function() {
            $(this).is(':checked') ? OrderAddressForm.hideBilling() : OrderAddressForm.showBilling();
        });


        $('#order_delivery_date').datepicker({
            dateFormat: 'dd/mm/yy',
            minDate: 1,
            maxDate: 100,
            numberOfMonths: 1,
            beforeShowDay: $.datepicker.noWeekends
        });

        $('#order_shiptocity').change(function() {

            var city = $(this).val();

            if(!city) OrderAddressForm.clearShipping();

        });

    },

    setShippingPrice: function(price) {

        price = parseFloat(price).toFixed(2)

        this.$shippingOptions.html('$'+price+'<span class="shipping-name">Delivery cost</span>');

        OrderAddressForm.options.shippingprice = price;

        OrderAddressForm.outputPriceSummary();

    },

    clearShipping: function() {

        this.$shippingOptions.html('');
        OrderAddressForm.options.shippingprice = 0;
        OrderAddressForm.outputPriceSummary();


    },

    hideBilling: function() {

        this.$billing.hide();
        this.form.validateForm();

    },

    showBilling: function() {

        this.$billing.stop().fadeIn()
        
    },


    outputPriceSummary: function() {

        var subtotalprice = parseFloat(OrderAddressForm.options.subtotalprice).toFixed(2);
        var shippingprice = parseFloat(OrderAddressForm.options.shippingprice).toFixed(2);
        var totalprice = (parseFloat(subtotalprice) + parseFloat(shippingprice)).toFixed(2);

        $('#cart-subtotal').html(subtotalprice);
        $('#shipping-price').html(shippingprice);
        $('#cart-total').html(totalprice);

        return this;

    }
    
}


var EnquiryForm = {

    init: function(elem, options) {

        this.options = $.extend({},this.options,options);
        this.el = elem;
        this.$el = $(elem);

        this.khfForm = this.$el.khfForm(this.options);

        this.initEventListeners();

        return this;

    },

    initEventListeners: function() {

        $('#enquirywedding_ceremonydate').datepicker({
            dateFormat: 'dd/mm/yy',
            minDate: 1,
            maxDate: 730,
            numberOfMonths: 1
        });

        $('#enquiryevent_date').datepicker({
            dateFormat: 'dd/mm/yy',
            minDate: 1,
            maxDate: 730,
            numberOfMonths: 1
        });
        
    },


    checkTopThreeConcerns: function() {

        this.$el.submit(function() {

            var count = 0;

            for(var i = 26; i < 36; i++) {

                if($('#enquiryoptionid'+i).is(':checked')) {

                    count++;

                }

            }

            if(count !== 3) {

                alert('Please select only 3 of your top ten concerns');

                return false;

            }


        });

    }

}


$.fn.suggest = function(options){

    var Suggest = this;
    
    this.onKeyUp = function(e) {

        var code = getKeyCode(e);

        for(var k in keys) {

            if(code === keys[k]) return false;

        }

        typedValue = $suggestor.val();

        if(!typedValue.length) {

            return false;

        }

        $.getJSON(app.URL.path+options.URL, { q: typedValue }, function(j) {

            if(j.length) {

                data = j;
                $suggestions.html('<ul></ul>');

                for(var d in j) {

                    $suggestions.find('ul').append('<li>'+j[d].html+'</li>');

                }

            }
            else {

                Suggest.clear();

            }

        });


    }

    this.onKeyDown = function(e) {

        var code = getKeyCode(e);

        if($suggestions.length) {

            switch (code) {

                case keys.UP:
                    scroll('up');
                    break;

                case keys.DOWN:
                    scroll('down');
                    break;

                case keys.TAB:
                    if($suggestions.find('.'+options.hoverClass).length) {
                        complete(getSuggestion());
                    }
                    Suggest.clear();
                    break;

                case keys.RETURN:
                    if($suggestions.find('.'+options.hoverClass).length) {
                        e.preventDefault();
                        complete(getSuggestion());
                        Suggest.clear();
                    }
                    break;

                case keys.ESC:
                    Suggest.clear();
                    break;

            }

        }

    }

    this.onChange = function(e) {

        if(typeof options.onChange === 'function') {

            options.onChange.call(this, $suggestor.val(), data);

        }

    }

    this.onSelect = function(text) {
        
        complete(text);
        Suggest.clear();

    }
    
    var getKeyCode = function(e) {

        return e.keyCode ? e.keyCode : e.which;
        
    }

    this.clear = function() {

        $suggestions.html('');
        indice = -1;

    }

    var complete = function(text) {

        $suggestor.val(text);

        if(typeof options.onChange === 'function') {

            options.onChange.call(this, text, data);

        }

    }

    var getSuggestion = function() {

        return $suggestions.find('.'+options.hoverClass).html();

    }
    
    var scroll = function(dir) {

        var suggestionCount = data.length;

        $suggestions.find('.' + options.hoverClass).removeClass(options.hoverClass);

        if(dir === 'down') {
            indice = (indice + 1) < suggestionCount ?  indice + 1 : -1;
        }
        else {
            indice = indice < 0 ? suggestionCount - 1 : ((indice - 1) < 0 ? -1 : indice - 1);
        }

        if(indice < 0) {
            
            complete(typedValue);

        }
        else {

            var $listItem = $suggestions.find('li:eq(' + indice + ')').addClass(options.hoverClass);
            complete($listItem.html());

        }

    }

    var init = function() {

        $('body').click(function() {
            Suggest.clear();
        });

        $suggestions.delegate('li', 'click', function(e) {
            e.stopPropagation();
            Suggest.onSelect(this.innerHTML);
        });


        $suggestor.keyup(function(e) {
            Suggest.onKeyUp(e);
        });

        $suggestor.keydown(function(e) {
            Suggest.onKeyDown(e);
        });

        $suggestor.change(function(e) {
            Suggest.onChange(e);
        });

        return this;

    }


    var keys = {
                RETURN:     13,
                ESC:        27,
                TAB:        9,
                UP:         38,
                DOWN:       40
            };

    var data = null;
    var indice = -1;
    var $suggestor = $(this);
    var $suggestions = $(options.target);
    var typedValue = null;

    var defaults = {
        target: '#suggestions',
        hoverClass: 'active',
        data: {}
    };
        

    options = $.extend({}, defaults, options);

    return this.each(function(){
        init();
    });


}

