;( function( $ ) {

    // static method
    $.shoppingcart = function()
    {
        return $( document ).data( "shoppingcart" );
    }

    //
    // plugin object
    //
    ShoppingCart.prototype =
    {
        init: function( options )
        {
            this.options = $.extend( {
                url: '',
                onQtyChange: function() {
                }
            }, options );
            this.products = {};
            this.fetchProducts_();
        },
        apply : function( fn )
        {
            if ( typeof(fn) == 'function' )
            {
                for ( var i in this.products )
                {
                    fn.call( null, i, this.products[i] );
                }
            }
        },
        add : function( id, qty )
        {
            if ( !this.exists_( id ) )
            {
                this.products[id] = qty || 1;
            }
            else
            {
                this.products[id] += qty || 1;
            }
            this.reset_();
            $( document ).trigger( 'basketchange' );
        },
        update : function( id, qty )
        {
            if ( !qty )
                return this.remove( id );
            if ( this.exists_( id ) )
            {
                this.products[id] = qty;
                this.reset_();
                $( document ).trigger( 'basketchange' );
            }
        },
        remove : function( id )
        {
            if ( this.exists_( id ) )
            {
                this.products[id] = null;
                try
                {
                    delete this.products[id];
                }
                catch ( e )
                { }
                this.reset_();
                $( document ).trigger( 'basketchange' );
            }
        },
        clear : function()
        {
            this.products = {};
            this.reset_();
            $( document ).trigger( 'basketchange' );
        },
        size : function()
        {
            var sz = 0;
            for ( var j in this.products )
            {
                ++sz;
            }
            return sz;
        },
        exists_ : function( id )
        {
            return this.products[id] != undefined;
        },
        reset_ : function()
        {
            if ( this.size() )
            {
                $.cookie( this.options.cookieArg, $.toJSON( this.products ), { path : '/' } );
            }
            else
            {
                $.cookie( this.options.cookieArg, null, { path : '/', expires : -1 } );
            }
        },
        fetchProducts_ : function()
        {
            var source = $.cookie( this.options.cookieArg );
            if ( source )
            {
                try
                {
                    var products = $.evalJSON( source );
                    for ( var i in products )
                    {
                        this.products[i] = products[i];
                    }
                }
                catch ( ex )
                {
                    alert( ex.message );
                }
            }
        }
    };
    ShoppingCart.prototype.constructor = ShoppingCart;
    function ShoppingCart()
    {
        this.init.apply( this, arguments );
    }

    // plugin
    $.fn.shoppingcart = function( options )
    {
        // options section
        var defaultOptions =
        {
            cookieArg: 'products'
        };
        options = $.extend( defaultOptions, options );

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

} )( jQuery );
