define([
                                'dojo/request/xhr',
                                'esri/request',
                                'dojo/Deferred'
                            ],
                            function (xhr, esriRequest, Deferred) {
                                //local properties
                                var states = null,
                                    mapCollection = null;
                            
                                //module
                                return {
                                    /**
                                    * Query all the states from the ArcGIS Server rest endpoint.
                                    * @method getAllStates
                                    *
                                    * @param {String} url
                                    * @return {Deferred} r
                                    */
                                    getAllStates: function (url) {
                                        //return stored object if exists
                                        if (states !== null) {
                                            var d = new Deferred();
                                            d.resolve(states);
                                            return d;
                                        }
                            
                                        //using esri request since it will auto-handle the proxy and cors
                                        var r = esriRequest({
                                            url: url + "/query",
                                            content: { f: "json", where: "1=1", orderByFields: "STUSAB", outFields: "STUSAB", returnDistinctValues: true, returnGeometry: false },
                                            handleAs: "json"
                                        });
                                        r.then(function (resultSet) {
                                            states = resultSet;
                                        });
                                        return r;
                                    },
                            
                                    /**
                                    * Query all the web map json records from the ArcGIS Server rest endpoint.
                                    * @method getMapCollection
                                    *
                                    * @param {String} url
                                    * @return {Deferred} r
                                    */
                                    getMapCollection: function (url) {
                                        //return stored object if exists
                                        if (mapCollection !== null) {
                                            var d = new Deferred();
                                            d.resolve(mapCollection);
                                            return d;
                                        }
                            
                                        //using esri request since it will auto-handle the proxy and cors
                                        var r = esriRequest({
                                            url: url + "/query",
                                            content: { f: "json", where: "1=1", outFields: "*", orderByFields: "MAP_NUMBER", returnGeometry: false },
                                            handleAs: "json"
                                        });
                                        return r;
                                    },
                            
                                    /**
                                    * Validate the application input token against the specified authentication service.
                                    * @method authenticateUserToken
                                    *
                                    * @param {String} url
                                    * @param {String} token
                                    * @return {Deferred} d
                                    */
                                    authenticateUserToken: function (url, token) {
                                        var d = new Deferred();
                                        if (!url || url == '') {
                                            d.reject("URL has not been specified.");
                                        }
                                        var r = xhr(url, {
                                            handleAs: "json"
                                        });
                                        r.then(function (response) {
                                            d.resolve(response);
                                        },
                                        function (err) {
                                            d.reject(err);
                                        });
                            
                                        return d;
                                    },
                            
                                    /**
                                    * Posts a web map json defintion to the specified service endpoint.
                                    * @method saveMap
                                    *
                                    * @param {String} url
                                    * @param {Object} input
                                    * @return {Deferred} d
                                    */
                                    saveMap: function (url, input) {
                                        var d = new Deferred();
                            
                                        if (!url || url == '') {
                                            d.reject("URL has not been specified.");
                                        }
                                        var r = xhr(url, {
                                            method: "POST",
                                            handleAs: "json",
                                            data: {
                                                token: input.token,
                                                mapNumber: input.mapNumber,
                                                jurisdictionId: input.jurisdictionId,
                                                mapName: input.mapName,
                                                mapDesc: input.mapDesc,
                                                map: input.map
                                            }
                                        });
                                        r.then(function (response) {
                                            d.resolve(response);
                                        },
                                        function (err) {
                                            d.reject(err);
                                        });
                            
                                        return d;
                                    }
                                };
                            });