(function ($) {
    var _currentState,

        _defaultOptions = {path: '/', params: {}},

        _deepLink = function (data) {
            var paramString = $.param(data.params);

            if (paramString.length > 0) {
                return data.path + '?' + paramString;
            }
            return data.path;
        },

        _changeTo = function (data) {
            var url = _deepLink(data);

            _changeToUrl(url);
        },

        _changeToUrl = function (url) {
            $.address.value(url);
            $.address.update();
            _syncWithAddress();
        },

        _syncWithAddress = function () {
            var data = {
                path: $.address.path(),
                params: {}
            };

            $.each($.address.parameterNames(), function (i, name) {
                data.params[name] = $.address.parameter(name);
            });

            _currentState = buildState(data);
        },

        buildState = function (options) {
            var data = {
                path: options.path,
                params: $.extend({}, options.params)
            };

            return {
                current: function () {
                    return buildState({
                        path: _currentState.path(),
                        params: _currentState.params()
                    });
                },
                
                path: function (path) {
                    if (path) {
                        data.path = path;
                        return this;
                    }

                    return data.path;
                },

                params: function (params) {
                    if (params) {
                        data.params = $.extend({}, params);
                        return this;
                    }

                    return $.extend({}, data.params)
                },

                param: function (name, value) {
                    if (!name) {
                        throw 'param requires a name';
                    }

                    if (value) {
                        data.params[name] = value;
                        return this;
                    }
                    else if (value === null) {
                        delete data.params[name];
                        return this;
                    }

                    return data.params[name];
                },

                update: function (url) {
                    if (url) {
                        _changeToUrl(url);
                        return;
                    }

                    _changeTo(data);
                },

                deepLink: function () {
                    return _deepLink(data);
                },

                onChange: function (changeCb) {
                    $.address.change(function (event) {
                        changeCb({
                            path: event.path,
                            params: event.parameters
                        });
                    });
                }
            };
        };

    $.address.autoUpdate(false);

    _currentState = buildState($.extend({}, _defaultOptions));



    $.location = function (options) {
        if (!options) {
            return buildState(_defaultOptions);
        }

        return buildState(options);
    };
})(jQuery);


