//IShoppingCartDiscountStrategy.prototype =
//{
//    applyDiscount: function( shoppingCart ) { }
//};

ShoppingCartSumtotalDiscountStrategy.prototype =
{
    criteria: [],
    applyDiscount: function( shoppingCart )
    {
        var overallDiscount = 0;
        for ( var i in this.criteria )
        {
            if ( this.criteria[i].sumtotal <= shoppingCart.subtotal )
            {
                overallDiscount = this.criteria[i].discount;
            }
            else
            {
                break;
            }
        }
        shoppingCart.discount = overallDiscount;
    }
}
ShoppingCartSumtotalDiscountStrategy.prototype.constructor = ShoppingCartSumtotalDiscountStrategy;
function ShoppingCartSumtotalDiscountStrategy( criteria )
{
    this.criteria = criteria || [];
    this.criteria.sort( function( lhs, rhs ) {
        return lhs.sumtotal - rhs.sumtotal;
    } );
}

ShoppingCartQuantityDiscountStrategy.prototype =
{
    criteria: [],
    applyDiscount: function( shoppingCart )
    {
        //this.criteria.sort( fucntion( lhs, rhs ) { return 0; } );
        var itemQuantity = 0;
        for ( var i in shoppingCart.items )
        {
            itemQuantity += shoppingCart.items[i].quantity;
        }
        var overallDiscount = 0;
        for ( var i in this.criteria )
        {
            if ( this.criteria[i].quantity <= itemQuantity )
            {
                overallDiscount = this.criteria[i].discount;
            }
            else
            {
                break;
            }
        }
        shoppingCart.discount = overallDiscount;
    }
}
ShoppingCartQuantityDiscountStrategy.prototype.constructor = ShoppingCartQuantityDiscountStrategy;
function ShoppingCartQuantityDiscountStrategy( criteria )
{
    this.criteria = criteria || [];
    this.criteria.sort( function( lhs, rhs ) {
        return lhs.quantity - rhs.quantity;
    } );
}

;( function( $ ) {

    $.basket = function()
    {
        return $( document ).data( "basket" );
    }

    //
    // item prototype
    //
    Item.prototype =
    {
        item: null, quantity: 1, price: 0.0, discount: 0, subtotal: 0.0, total: 0.0,
        onQuantityChange_: function()
        {
            var subtotal = this.quantity * this.price;
            this.subtotal = parseFloat( subtotal - subtotal * this.discount / 100 );
            this.total = parseFloat( this.subtotal - this.subtotal * this.discount / 100 );
        },
        update: function( quantity )
        {
            this.quantity = quantity;
            this.onQuantityChange_( this );
        }
    };
    Item.prototype.constructor = Item;
    function Item( item, quantity, price, discount )
    {
        this.item = item;
        this.quantity = quantity;
        this.price = parseFloat( price );
        this.discount = discount;
        this.onQuantityChange_( this );
    }

    //
    // plugin object
    //
    ShoppingCart.prototype =
    {
        init: function( options )
        {
            this.options = options;
            this.items = {};
            this.subtotal = 0.0;
            this.total = 0.0;
            this.discount = 0;
            this.fetch_();
            if ( this.options.params )
            {
                this.loadParams_();
            }
        },
        apply : function( fn )
        {
            if ( typeof(fn) == 'function' )
            {
                for ( var i in this.items )
                {
                    fn.call( null, this.items[i] );
                }
            }
        },
        add : function( item, quantity, price, discount )
        {
            if ( !this.exists_( item ) )
            {
                this.items[item] = new Item( item, quantity || 1, price || 0.0, discount || 0 );
            }
            else
            {
                this.items[item].update( this.items[item].quantity + quantity || 1 );
            }
            this.reset_();
            $( document ).trigger( 'basketchange' );
        },
        modify : function( item, quantity )
        {
            if ( this.exists_( item ) )
            {
                this.items[item].update( quantity );
                this.reset_();
                $( document ).trigger( 'basketchange' );
            }
        },
        remove : function( item )
        {
            if ( this.exists_( item ) )
            {
                this.items[item] = null;
                try
                {
                    delete this.items[item];
                }
                catch ( e )
                { }
                this.reset_();
                $( document ).trigger( 'basketchange' );
            }
        },
        clear : function()
        {
            this.items = {};
            this.reset_();
            $( document ).trigger( 'basketchange' );
        },
        size : function()
        {
            var sz = 0;
            for ( var j in this.items )
            {
                ++sz;
            }
            return sz;
        },
        exists_ : function( item )
        {
            return this.items[item] != undefined;
        },
        reset_ : function()
        {
            if ( this.size() )
            {
                this.calcSubtotal_();
                $.cookie( this.options.cookieArg, $.toJSON( this.items ), { path : '/' } );
            }
            else
            {
                $.cookie( this.options.cookieArg, null, { path : '/', expires : -1 } );
            }
        },
        calcSubtotal_: function()
        {
            var overallSubtotal = 0.0;
            this.apply( function( item ) {
                overallSubtotal += item.total;
            } );
            this.subtotal = parseFloat( overallSubtotal );
            // do call discount strategy to calc discount
            this.applyDiscount_();
            this.total = parseFloat( this.subtotal - this.subtotal * this.discount / 100 );
        },
//if ( this.options.discountStrategy instanceof ShoppingCartSumtotalDiscountStrategy )
        applyDiscount_: function()
        {
            if ( this.options.discountStrategy && this.options.discountStrategy.applyDiscount )
            {
                this.options.discountStrategy.applyDiscount( this );
            }
        },
        loadParams_ : function()
        {
            if ( this.options.params && $.cookie( 'params' ) )
            {
                this.options.params = $.evalJSON( $.cookie( 'params' ) );
            }
        },
        saveParams_ : function()
        {
            if ( this.options.params )
            {
                $.cookie( 'params', $.toJSON( this.options.params ), { path : '/' } );
            }
            else
            {
                $.cookie( 'params', null, { path : '/', expires : -1 } );
            }
        },
        fetch_ : function()
        {
            this.items = {};
            if ( $.cookie( this.options.cookieArg ) )
            {
                try
                {
                    var items = $.evalJSON( $.cookie( this.options.cookieArg ) );
                    for ( var i in items )
                    {
                        this.add( items[i].item, items[i].quantity, items[i].price, items[i].discount );
                    }
                    //this.calcSubtotal_();
                }
                catch ( ex )
                {
                    alert( ex.message );
                }
            }
        },
        setParam: function( param, value )
        {
            this.options.params[param] = value;
            this.saveParams_();
        }
    };
    ShoppingCart.prototype.constructor = ShoppingCart;
    function ShoppingCart()
    {
        this.init.apply( this, arguments );
    }

    // plugin
    $.fn.basket = function( options )
    {
        // options section
        var defaultOptions =
        {
            cookieArg: 'basket',
            params: null,
            discountStrategy: null
        };
        options = $.extend( defaultOptions, options );

        if ( !$( document ).data( "basket" ) )
        {
            $( document ).data( "basket", new ShoppingCart( options ) )
        }
        return this;
    }

} )( jQuery );