/**
 * smartflousersapi
 */

/**
 * Represents remote SmartFlo™ User Service APIs.
 * It is expected that this class will be injected into an
 * Angular module as a service.
 * <br><br>
 * This AngularJS service is built upon the SmartFlo™ RESTful Service APIs 
 * for user managment in the SmartFlo™ system. It is provided 
 * to remove some of the complexities entailed by using RESTful APIs.
 * @description <strong>Warning!</strong> The SmartFlo™ APIs assume 2 global 
 * variables are set in 
 * $rootScope prior to using the APIs:
 * <ol>
 * <li><code>$rootScope.credential</code></li> set implicitely by the AuthAPI 
 * class upon success of the authenticate method
 * <li><code>$rootScope.site</code></li> set by the calling application to the  
 * domain (e.g., www.smartflo.biz) or IP address of the target SmartFlo™ system, 
 * possibly when initializing the module that declares an API service
 * </ol>
 * @copyright © Chalex Corp. 2002 - 2017. All rights reserved.
 * @example 
 * //
 * // Warning! The global '$rootScope.site' field value must be set 
 * // to the target SmartFlo™ domain prior to using theSmartFlo™ APIs. In this 
 * // example it is set by the configuration block of the 'SFusersApi' 
 * // module.
 * //
 * angular.module('sf-users', [])
 *      // inject API as a service
 *      .service('SFusersApi', ['$rootScope', '$http', UsersAPI])
 *      .controller('SFUsersCtrl', UsersCtrl);
 *      .run(function ($rootScope, $location) { 
 *      // store the site for use by APIs
 *          $rootScope.site = $location.host();
 *          if ($location.port !== null & $location.port !== 80) {
 *          $rootScope.site += ':' + $location.port().toString();
 *     }
 * });
 * @constructor 
 * @param {object} $rootScope - The topmost parent scope in AngularJS.
 * @param {service} $http - The core AngularJS service that facilitates 
 * communication with the remote HTTP servers via the browser's XMLHttpRequest 
 * object or via JSONP.
 * @returns {class} A constructor that will be instantiated.
 */

class UsersAPI {
    constructor($rootScope, $http) {
        return {
            
            /** 
             * Deletes a user from the system.
             * @function 
             * @name deleteUser
             * @description Deletes a user from the system, this will set their status to ACCOUNT_DELETED preventing 
             * them from appearing as a result in any getUser() type calls.
             * @memberof UsersAPI.prototype
             * @param {object} params - An object providing the userid for the user selected for deletion.
             * @param {function} successHandler - A function that is 
             * called back upon success.
             * @param {function} [failureHandler] - An optional 
             * function that is called back upon failure. If none is specified,
             * the success callback is called with failure data. On failure 
             * however, the only valid fields returned are: 
             * <code>status, statusMessage, api</code> and <code>date</code>.
             * @throws (string) "missing.callback.exception"
             * @throws {} $http errors
             * @returns {object} A result object. 
             * <pre><code>
             * result {
             *      api: "adm::delete::userregistrations,
             *      date: [Date object providing time call was made],
             *      status: '0',
             *      statusMessage: "adm.no.errors"    
             * };</pre></code>
             * @example 
             * $scope.deleteUser = function() {
             *     var params = {
             *         userid: $scope.userID     
             *     };
             *     usersApi.deleteUser(params, deleteUserHandler);                
             * };

             * function deleteUserHandler(result){
             *     if (result.status === '0'){
             *         console.log("user deleted: " + $scope.userID);
             *         var msg = $translate.instant('user.deleted');
             *         $scope.feedbackMessage = msg;
             *         setTimeoutMessage();
             *         $scope.refreshUsers();
             *     } else {
             *         $scope.errorCode = result.status;
             *         $scope.errorMessage = result.statusMessage;
             *     }
             * }
             */
        
            deleteUser: function(params, successHandler, failureHandler) {
                // require a successHandler
                if (!successHandler) {
                    throw new Error("missing.callback.exception");
                }
                
                // if no failureHandler is defined, use successHandler as 
                // general callback
                if (!failureHandler) {
                    failureHandler = successHandler;
                }

                var result = del('userregistrations?', params);
                result.then(function (result) {
                    var x2js = new X2JS();
                    var jsonData = x2js.xml_str2json(result.data);
                    var response = {};
                    
                    response.date = new Date();
                    response.api = jsonData.adm_service_response.api;
                    response.status = jsonData.adm_service_response.error_response.response_code;
                    response.statusMessage = jsonData.adm_service_response.error_response.response_message;
                    
                    if (response.status === '0') {
                        successHandler(result);
                    } else {
                        failureHandler(result);
                    }
                },
                function (errorInfo) {
                    throw new Error(errorInfo.data);
                });
            },
            
            /** 
             * Retrieves a list of all affiliates.
             * @function 
             * @name getAffiliates
             * @description Retrieves a list of affiliates.
             * @memberof UsersAPI.prototype
             * @param {function} successHandler - A function that is 
             * called back upon success.
             * @param {function} [failureHandler] - An optional 
             * function that is called back upon failure. If none is specified,
             * the success callback is called with failure data. On failure 
             * however, the only valid fields returned are: 
             * <code>status, statusMessage, api</code> and <code>date</code>.
             * @throws (string) "missing.callback.exception"
             * @throws {} $http errors
             * @returns {object} A result object. 
             * <pre><code>
             * result {
             *      api: "adm::get::affiliates,
             *      date: [Date object providing time call was made],
             *      status: '0',
             *      statusMessage: "adm.no.errors",
             *      affiliates: [an array of strings]
             * };</pre></code>
             * @example 
             * usersApi.getAffiliates(getAffiliatesHandler);
             *
             * function getAffiliatesHandler(result) {
             *     if (result.status === '0'){
             *         $scope.affiliates = result.affiliates;
             *     } else {
             *         $scope.errorCode = result.status;
             *         $scope.errorMessage = result.statusMessage;
             *     }
             * }
             */
            
            getAffiliates: function(successHandler, failureHandler) {
                // require a successHandler
                if (!successHandler) {
                    throw new Error("missing.callback.exception");
                }
                
                // if no failureHandler is defined, use successHandler as 
                // general callback
                if (!failureHandler) {
                    failureHandler = successHandler;
                }

                var result = get('affiliates');
                result.then(function (response) {
                    var x2js = new X2JS();
                    var jsonData = x2js.xml_str2json(response.data);
                    var affiliateData = {};
                    
                    affiliateData.api = jsonData.adm_service_response.api;
                    affiliateData.status = jsonData.adm_service_response.error_response.response_code;
                    affiliateData.statusMessage = jsonData.adm_service_response.error_response.response_message;
                    
                    if (affiliateData.status === '0') {
                        var affiliates = jsonData.adm_service_response.response.resource_group_list.resource_group;
                        if (affiliates && !Array.isArray(affiliates)) {
                            var tmp = [];
                            tmp.push(affiliates);
                            affiliates = tmp;
                        } else if (!affiliates) {
                            affiliates = [];
                        }
                        
                        affiliateData.affiliates = affiliates;
                        successHandler(affiliateData);
                    } else {
                        failureHandler(affiliateData);
                    }
                },
                function (errorInfo) {
                    throw new Error(errorInfo.data);
                });
            },
            
            /** 
             * Retrieves a list of registered users.
             * @function 
             * @name getUserRegistrations
             * @description Retrieves a list of registered users as an array of objects with each element containing a set of 
             * fields for an individual user. These fields include the affiliate, email, status, user id, and name.
             * @memberof UsersAPI.prototype
             * @param {function} successHandler - A function that is 
             * called back upon success.
             * @param {function} [failureHandler] - An optional 
             * function that is called back upon failure. If none is specified,
             * the success callback is called with failure data. On failure 
             * however, the only valid fields returned are: 
             * <code>status, statusMessage, api</code> and <code>date</code>.
             * @throws (string) "missing.callback.exception"
             * @throws {} $http errors
             * @returns {object} A result object. 
             * <pre><code>
             * result {
             *      api: "adm::get::userregistrations", // name of the call
             *      date: [Date object providing time call was made],
             *      status: '0',
             *      statusMessage: "adm.no.errors"
             *      userRegistrations: [an array of objects describing user registration information
             *                - e.g., object1 {  affiliate: [the affiliate this user is a member of]
             *                                   user_email: [the users email]
             *                                   user_status: [current status of the user, either ACCOUNT_ACTIVE, ACCOUNT_SUSPENDED or ACCOUNT_DELETED]
             *                                   userid: [the users id]
             *                                   username: [the users name] 
             *                                }]
             * };</pre></code>
             * @example 
             *  usersApi.getUserRegistrations(getUserRegistrationsHandler);
             *
             * function getUserRegistrationsHandler(result) {
             *     if (result.status === '0'){
             *         setUserData(result.userRegistrations);
             *     } else {
             *         $scope.errorCode = result.status;
             *         $scope.errorMessage = result.statusMessage;
             *     }
             * }
             */
            
            getUserRegistrations: function(successHandler, failureHandler) {
                // require a successHandler
                if (!successHandler) {
                    throw new Error("missing.callback.exception");
                }
                
                // if no failureHandler is defined, use successHandler as 
                // general callback
                if (!failureHandler) {
                    failureHandler = successHandler;
                }
                
                var result = get('userregistrations');
                result.then(function (result) {
                    var x2js = new X2JS();
                    var jsonData = x2js.xml_str2json(result.data);
                    var registrationData = {};
                    
                    registrationData.date = new Date();
                    registrationData.api = jsonData.adm_service_response.api;
                    registrationData.status = jsonData.adm_service_response.error_response.response_code;
                    registrationData.statusMessage = jsonData.adm_service_response.error_response.response_message;
                    
                    if (registrationData.status === '0'){
                        var userRegistrations = jsonData.adm_service_response.response.user_registration_list.user_registration;
                        if (userRegistrations && !Array.isArray(userRegistrations)) {
                            var tmp = [];
                            tmp.push(userRegistrations);
                            userRegistrations = tmp;
                        } else if (!userRegistrations) {
                            userRegistrations = [];
                        }

                        registrationData.userRegistrations = userRegistrations;
                        successHandler(registrationData);
                    } else {
                        failureHandler(registrationData);
                    }
                },
                function (errorInfo) {
                    throw new Error(errorInfo.data);
                });
            },
            
             /** 
             * Registers a new user.
             * @function 
             * @name postAddUser
             * @description Registers a new user in a selected affiliate.
             * @memberof UsersAPI.prototype
             * @param {object} params - An object providing the username, userid, useremail, 
             * affiliate, and affiliatepassword that is necessary to register a user in the system.
             * @param {function} successHandler - A function that is 
             * called back upon success.
             * @param {function} [failureHandler] - An optional 
             * function that is called back upon failure. If none is specified,
             * the success callback is called with failure data. On failure 
             * however, the only valid fields returned are: 
             * <code>status, statusMessage, api</code> and <code>date</code>.
             * @throws (string) "missing.callback.exception"
             * @throws {} $http errors
             * @returns {object} A result object. 
             * <pre><code>
             * result {
             *      api: "adm::post::userregistrations, 
             *      date: [Date object providing time call was made],
             *      status: '0',
             *      statusMessage: "adm.no.errors"
             * };</pre></code>
             * @example 
             * $scope.registerUser = function(username, userid, useremail, affiliatepassword) {
             *     var param = {
             *            username: username,
             *            userid: userid,
             *            useremail: useremail,
             *            affiliate: $scope.affiliate,
             *            affiliatepassword: affiliatepassword
             *     };
             *     usersApi.postAddUser(params, registerUserHandler);
             * };
             *
             * function registerUserHandler(result){
             *     if (result.status === '0'){
             *        $scope.msg = $translate.instant('user.registered');
             *        $scope.feedbackMessage = msg;
             *     } else {
             *         $scope.errorCode = result.status;
             *         $scope.errorMessage = result.statusMessage; 
             *     }
             * }
             */
            
            postAddUser: function(params, successHandler, failureHandler) {
                // require a successHandler
                if (!successHandler) {
                    throw new Error("missing.callback.exception");
                }
                
                // if no failureHandler is defined, use successHandler as 
                // general callback
                if (!failureHandler) {
                    failureHandler = successHandler;
                }

                var result = post('userregistrations?', params);
                result.then(function (response) {
                    var x2js = new X2JS();
                    var jsonData = x2js.xml_str2json(response.data);
                    var response = {};
                    
                    response.date = new Date();
                    response.api = jsonData.adm_service_response.api;
                    response.status = jsonData.adm_service_response.error_response.response_code;
                    response.statusMessage= jsonData.adm_service_response.error_response.response_message;
                    response.userData = jsonData.adm_service_response.response.user_registration_list.user_registration;
                    
                    if (response.status === '0') {
                        successHandler(response);
                    } else {
                        failureHandler(response);
                    }
                },
                function (errorInfo) {
                    throw new Error(errorInfo.data);
                });
            },
            
            /** 
             * Changes a user's email address.
             * @function 
             * @name postChangeEmail
             * @description Changes a user's email address.
             * @memberof UsersAPI.prototype
             * @param {object} params - An object providing the userid and email that is necessary
             *  to change a users email address.
             * @param {function} successHandler - A function that is 
             * called back upon success.
             * @param {function} [failureHandler] - An optional 
             * function that is called back upon failure. If none is specified,
             * the success callback is called with failure data. On failure 
             * however, the only valid fields returned are: 
             * <code>status, statusMessage, api</code> and <code>date</code>.
             * @throws (string) "missing.callback.exception"
             * @throws {} $http errors
             * @returns {object} A result object. 
             * <pre><code>
             * result {
             *      api: "adm::post::userregistrations",
             *      date: [Date object providing time call was made], 
             *      status: '0',
             *      statusMessage: "adm.no.errors"  
             * };</pre></code>
             * @example 
             * $scope.changeEmail = function(newemail) {
             *      var param = {
             *          userid: $scope.userID,
             *          newemail: newemail
             *      };
             *      usersApi.postChangeEmail(param, changeEmailHandler);
             *  };
             *
             * function changeEmailHandler(result){
             *      if (result.status === '0'){
             *          var msg = $translate.instant('user.email.changed');
             *          $scope.feedbackMessage = msg;
             *      } else {
             *          $scope.errorCode = result.status;
             *          $scope.errorMessage = result.statusMessage;
             *      }
             *  }
             */
            
            postChangeEmail: function(params, successHandler, failureHandler){
                // require a successHandler
                if (!successHandler) {
                    throw new Error("missing.callback.exception");
                }
                
                // if no failureHandler is defined, use successHandler as 
                // general callback
                if (!failureHandler) {
                    failureHandler = successHandler;
                }
                
                var result = post('userregistrations?', params);
                result.then(function (response) {
                    var x2js = new X2JS();
                    var jsonData = x2js.xml_str2json(response.data);
                    var response = {};
                    
                    response.date = new Date();
                    response.api = jsonData.adm_service_response.api;
                    response.status = jsonData.adm_service_response.error_response.response_code;
                    response.statusMessage = jsonData.adm_service_response.error_response.response_message;
                    
                    if (response.status === '0') {
                        successHandler(response);
                    } else {
                        failureHandler(response);
                    }   
                },
                function (errorInfo) {
                    throw new Error(errorInfo.data);
                });
            }
            
            
        };
        
        function get(path, param) {
            return request("GET", path, param);
        }

        function post(path, param, data) {
            return request("POST", path, param, data);
        }

        function put(path, param, data) {
            return request("PUT", path, param, data);
        }

        function del(path, param) {
            return request("DELETE", path, param);
        }

        function request(verb, path, param, data) {
            var site = $rootScope.site;
            var token = null;
            if (validData($rootScope.credential) && validData($rootScope.credential.token)) {
                token = $rootScope.credential.token;
            }
            var req = {
                method: verb,
                url: url(site, token, path, param),
                headers: {
                    'Authorization': getAuthHeader()
                },
                data: validData(data) ? data : null
            };
            return $http(req);
        }

        function url(site, token, path, param) {
            var reqUrl = 'https://' + site + '/api/' + token + '/adm/';
            if (validData(path)) {
                reqUrl += path;
            }

            if (validData(param)) {
                reqUrl += $.param(param);
            }
            return reqUrl;
        }
        
        function validData(data) {
            return data !== undefined && data !== null;
        }

        function getAuthHeader() {
            return "";
        }
    }
}




/**
 * smartflogroupsapi
 */

/**
 * Represents remote SmartFlo™ Groups Service APIs.
 * It is expected that this class will be injected into an
 * Angular module as a service.
 * <br><br>
 * This AngularJS service is built upon the SmartFlo™ RESTful Service APIs 
 * for group managment in the SmartFlo™ system. It is provided 
 * to remove some of the complexities entailed by using RESTful APIs.
 * @description <strong>Warning!</strong> The SmartFlo™ APIs assume 2 global 
 * variables are set in 
 * $rootScope prior to using the APIs:
 * <ol>
 * <li><code>$rootScope.credential</code></li> set implicitely by the AuthAPI 
 * class upon success of the authenticate method
 * <li><code>$rootScope.site</code></li> set by the calling application to the  
 * domain (e.g., www.smartflo.biz) or IP address of the target SmartFlo™ system, 
 * possibly when initializing the module that declares an API service
 * </ol>
 * @copyright © Chalex Corp. 2002 - 2017. All rights reserved.
 * @example 
 * //
 * // Warning! The global '$rootScope.site' field value must be set 
 * // to the target SmartFlo™ domain prior to using the SmartFlo™ APIs. In this 
 * // example it is set by the configuration block of the 'SFgroupsApi' 
 * // module.
 * //
 * angular.module('sf-groups', [])
 *      // inject API as a service
 *      .service('SFgroupsApi', ['$rootScope', '$http', GroupsAPI])
 *      .controller('SFgroupsCtrl', GroupsCtrl);
 *      .run(function ($rootScope, $location) { 
 *      // store the site for use by APIs
 *          $rootScope.site = $location.host();
 *          if ($location.port !== null & $location.port !== 80) {
 *          $rootScope.site += ':' + $location.port().toString();
 *     }
 * });
 * @constructor 
 * @param {object} $rootScope - The topmost parent scope in AngularJS.
 * @param {service} $http - The core AngularJS service that facilitates 
 * communication with the remote HTTP servers via the browser's XMLHttpRequest 
 * object or via JSONP.
 * @returns {class} A constructor that will be instantiated.
 */

class GroupsAPI {
    constructor($rootScope, $http) {
        return {
            
            /** 
             * Deletes a public group.
             * @function 
             * @name deletePublicGroup
             * @description Deletes a public group.
             * @memberof GroupsAPI.prototype
             * @param {object} params - An object providing the selected public group 
             * that will be set for deletion.
             * @param {function} successHandler - A function that is 
             * called back upon success.
             * @param {function} [failureHandler] - An optional 
             * function that is called back upon failure. If none is specified,
             * the success callback is called with failure data. On failure 
             * however, the only valid fields returned are: 
             * <code>status, statusMessage, api</code> and <code>date</code>.
             * @throws (string) "missing.callback.exception"
             * @throws {} $http errors
             * @returns {object} A result object. 
             * <pre><code>
             * result {
             *      api: "adm::delete::publicgroups,
             *      date: [Date object providing time call was made],
             *      status: '0',
             *      statusMessage: "adm.no.errors"
             * };</pre></code>
             * @example 
             * $scope.deletePublicGroup = function() {
             *     var param = {
             *         groupname: $scope.selectedPublicGroup
             *     };
             *     groupsApi.deletePublicGroup(param, deletePublicGroupHandler);
             *  };
             *
             * function deletePublicGroupHandler(result){
             *     if (result.status === '0'){
             *         groupsApi.getPublicGroups(getPublicGroupsHandler);
             *     } else {
             *         $scope.errorCode = result.status;
             *         $scope.errorMessage = result.statusMessage;
             *     }  
             * }
             */
            
            deletePublicGroup: function(params, successHandler, failureHandler) {
                // require a successHandler
                if (!successHandler) {
                    throw new Error("missing.callback.exception");
                }
                
                // if no failureHandler is defined, use successHandler as 
                // general callback
                if (!failureHandler) {
                    failureHandler = successHandler;
                }
                
                var result = del('publicgroups?', params);
                result.then(function (response) {
                    var x2js = new X2JS();
                    var jsonData = x2js.xml_str2json(response.data);
                    var response = {};
                    
                    response.date = new Date();
                    response.api = jsonData.adm_service_response.api;
                    response.status = jsonData.adm_service_response.error_response.response_code;
                    response.statusMessage = jsonData.adm_service_response.error_response.response_message;
                    
                    if (response.status === '0') {
                        successHandler(response);
                    } else {
                        failureHandler(response);
                    }
                },
                function (errorInfo) {
                    throw new Error(errorInfo.data);
                });
                
            },
            
            /** 
             * Deletes a user from a public group.
             * @function 
             * @name deleteUserFromPublicGroup
             * @description Deletes a user from a public group.
             * @memberof GroupsAPI.prototype
             * @param {object} params - An object providing the selected public group and 
             * public group user that will be set for deletion. 
             * that will be set for deletion.
             * @param {function} successHandler - A function that is 
             * called back upon success.
             * @param {function} [failureHandler] - An optional 
             * function that is called back upon failure. If none is specified,
             * the success callback is called with failure data. On failure 
             * however, the only valid fields returned are: 
             * <code>status, statusMessage, api</code> and <code>date</code>.
             * @throws (string) "missing.callback.exception"
             * @throws {} $http errors
             * @returns {object} A result object. 
             * <pre><code>
             * result {
             *      api: "adm::delete::publicgroupuser",
             *      date: [Date object providing time call was made],
             *      status: '0',
             *      statusMessage: "adm.no.errors"
             * };</pre></code>
             * @example 
             * $scope.deleteUserFromPublicGroup = function(){
             *     var param = {
             *         userid: $scope.selectedPublicGroupUser,
             *         groupname: $scope.selectedPublicGroup
             *     };
             *     groupsApi.deleteUserFromPublicGroup(param, deleteUserFromPublicGroupHandler);
             * };
             *
             * function deleteUserFromPublicGroupHandler(result){
             *     if (result.status === '0'){
             *         console.log("delete user from public group");
             *         getPublicGroupUsers();
             *     } else {
             *         $scope.errorCode = result.status;
             *         $scope.errorMessage = result.statusMessage;
             *     }
             * }
             */
            
            deleteUserFromPublicGroup: function(params, successHandler, failureHandler) {
                // require a successHandler
                if (!successHandler) {
                    throw new Error("missing.callback.exception");
                }
                
                // if no failureHandler is defined, use successHandler as 
                // general callback
                if (!failureHandler) {
                    failureHandler = successHandler;
                }
                
                var result = del('publicgroupuser?', params);
                result.then(function (response) {
                    var x2js = new X2JS();
                    var jsonData = x2js.xml_str2json(response.data);
                    var response = {};
                    
                    response.date = new Date();
                    response.api = jsonData.adm_service_response.api;
                    response.status = jsonData.adm_service_response.error_response.response_code;
                    response.statusMessage = jsonData.adm_service_response.error_response.response_message;
                    
                    if (response.status === '0') {
                        successHandler(response);
                    } else {
                        failureHandler(response);
                    }
                },
                function (errorInfo) {
                    throw new Error(errorInfo.data);
                });
                
            },

            /** 
             * Deletes a user from a system group.
             * @function 
             * @name deleteUserFromSystemGroup
             * @description Deletes a user from a system group.
             * @memberof GroupsAPI.prototype
             * @param {object} params - An object providing the system group and system group user 
             * that will be set for deletion.
             * @param {function} successHandler - A function that is 
             * called back upon success.
             * @param {function} [failureHandler] - An optional 
             * function that is called back upon failure. If none is specified,
             * the success callback is called with failure data. On failure 
             * however, the only valid fields returned are: 
             * <code>status, statusMessage, api</code> and <code>date</code>.
             * @throws (string) "missing.callback.exception"
             * @throws {} $http errors
             * @returns {object} A result object. 
             * <pre><code>
             * result {
             *      api: "adm::delete::systemgroupuser"
             *      date: [Date object providing time call was made],
             *      status: '0',
             *      statusMessage: "adm.no.errors"
             * };</pre></code>
             * @example 
             * $scope.deleteUserFromSystemGroup = function(){
             *      var param = {
             *          userid: $scope.systemGroupUser,
             *          groupname: $scope.systemGroup
             *      };
             *      groupsApi.deleteUserFromSystemGroup(param, deleteUserFromSystemGroupHandler);
             *  };

             *  function deleteUserFromSystemGroupHandler(result) {
             *      if (result.status === '0'){
             *          console.log("User deleted");
             *      } else {
             *          $scope.errorCode = result.status;
             *          $scope.errorMessage = result.statusMessage;
             *      }
             *  }
             */
            
            deleteUserFromSystemGroup: function(params, successHandler, failureHandler) {
                // require a successHandler
                if (!successHandler) {
                    throw new Error("missing.callback.exception");
                }
                
                // if no failureHandler is defined, use successHandler as 
                // general callback
                if (!failureHandler) {
                    failureHandler = successHandler;
                }
                
                var result = del('systemgroupuser?', params);
                result.then(function (response) {
                    var x2js = new X2JS();
                    var jsonData = x2js.xml_str2json(response.data);
                    var response = {};
                    
                    response.date = new Date();
                    response.api = jsonData.adm_service_response.api;
                    response.status = jsonData.adm_service_response.error_response.response_code;
                    response.statusMessage = jsonData.adm_service_response.error_response.response_message;
                    
                    if (response.status === '0') {
                        successHandler(response);
                    } else {
                        failureHandler(response);
                    }
                },
                function (errorInfo) {
                    throw new Error(errorInfo.data);
                });
            },
            
            /** 
             * Retrieves a list of system groups.
             * @function 
             * @name getSystemGroups
             * @description Retrieves a list of system groups.
             * @memberof GroupsAPI.prototype
             * @param {function} successHandler - A function that is 
             * called back upon success.
             * @param {function} [failureHandler] - An optional 
             * function that is called back upon failure. If none is specified,
             * the success callback is called with failure data. On failure 
             * however, the only valid fields returned are: 
             * <code>status, statusMessage, api</code> and <code>date</code>.
             * @throws (string) "missing.callback.exception"
             * @throws {} $http errors
             * @returns {object} A result object. 
             * <pre><code>
             * result {
             *      api: "adm::get::systemgroups",
             *      date: [Date object providing time call was made],
             *      status: '0',
             *      statusMessage: "adm.no.errors",
             *      systemGroups: [an array of strings]
             * };</pre></code>
             * @example 
             * groupsApi.getSystemGroups(getSystemGroupsHandler);
             *
             * function getSystemGroupsHandler(result){
             *     if (result.status === '0'){
             *         $scope.systemGroups = result.systemGroups;
             *      } else {
             *         $scope.errorCode = result.status;
             *         $scope.errorMessage = result.statusMessage;
             *      }
             * }
             */
            
            getSystemGroups: function(successHandler, failureHandler) {
                // require a successHandler
                if (!successHandler) {
                    throw new Error("missing.callback.exception");
                }
                
                // if no failureHandler is defined, use successHandler as 
                // general callback
                if (!failureHandler) {
                    failureHandler = successHandler;
                }
                
                var result = get('systemgroups');
                result.then(function (response) {
                    var x2js = new X2JS();
                    var jsonData = x2js.xml_str2json(response.data);
                    var systemGroupsData = {};
                    
                    systemGroupsData.date = new Date();
                    systemGroupsData.api = jsonData.adm_service_response.api;
                    systemGroupsData.status = jsonData.adm_service_response.error_response.response_code;
                    systemGroupsData.statusMessage = jsonData.adm_service_response.error_response.response_message;
                    
                    if (systemGroupsData.status === '0'){
                        var systemGroups = jsonData.adm_service_response.response.system_group_list.system_group;
                        if (systemGroups && !Array.isArray(systemGroups)) {
                            var tmp = [];
                            tmp.push(systemGroups);
                            systemGroups = tmp;
                        } else if (!systemGroups) {
                            systemGroups = [];
                        }

                        systemGroupsData.systemGroups = systemGroups;
                        successHandler(systemGroupsData);
                    } else {
                        failureHandler(systemGroupsData);
                    }
                },
                function (errorInfo) {
                    throw new Error(errorInfo.data);
                });
                
            },
            
            /** 
             * Retrieves a list of public groups.
             * @function 
             * @name getPublicGroups
             * @description Retrieves a list of public groups.
             * @memberof GroupsAPI.prototype
             * @param {function} successHandler - A function that is 
             * called back upon success.
             * @param {function} [failureHandler] - An optional 
             * function that is called back upon failure. If none is specified,
             * the success callback is called with failure data. On failure 
             * however, the only valid fields returned are: 
             * <code>status, statusMessage, api</code> and <code>date</code>.
             * @throws (string) "missing.callback.exception"
             * @throws {} $http errors
             * @returns {object} A result object. 
             * <pre><code>
             * result {
             *      api: "adm::get::publicgroups",
             *      date: [Date object providing time call was made],
             *      status: '0',
             *      statusMessage: "adm.no.errors",
             *      publicGroups: [an array of strings]
             * };</pre></code>
             * @example 
             * groupsApi.getPublicGroups(getPublicGroupsHandler);
             *
             * function getPublicGroupsHandler(result){
             *     if (result.status === '0'){
             *         $scope.publicGroups = result.publicGroups;
             *      } else {
             *         $scope.errorCode = result.status;
             *         $scope.errorMessage = result.statusMessage;
             *      }
             * }
             */
            
            getPublicGroups: function(successHandler, failureHandler) {
                // require a successHandler
                if (!successHandler) {
                    throw new Error("missing.callback.exception");
                }
                
                // if no failureHandler is defined, use successHandler as 
                // general callback
                if (!failureHandler) {
                    failureHandler = successHandler;
                }
                
                var result = get('publicgroups');
                result.then(function (response) {
                    var x2js = new X2JS();
                    var jsonData = x2js.xml_str2json(response.data);
                    var publicGroupsData = {};
                    
                    publicGroupsData.date = new Date();
                    publicGroupsData.api = jsonData.adm_service_response.api;
                    publicGroupsData.status = jsonData.adm_service_response.error_response.response_code;
                    publicGroupsData.statusMessage = jsonData.adm_service_response.error_response.response_message;
                    
                    if (publicGroupsData.status === '0'){
                        var publicGroups = jsonData.adm_service_response.response.public_group_list.public_group;
                        if (publicGroups && !Array.isArray(publicGroups)) {
                            var tmp = [];
                            tmp.push(publicGroups);
                            publicGroups = tmp;
                        } else if (!publicGroups) {
                            publicGroups = [];
                        }

                        publicGroupsData.publicGroups = publicGroups;
                        successHandler(publicGroupsData);
                    } else {
                        failureHandler(publicGroupsData);
                    }
                },
                function (errorInfo) {
                    throw new Error(errorInfo.data);
                });
                
            },
            
            /** 
             * Retrieves a list of assignable users within the resource group that user belongs to.
             * @function 
             * @name getPublicGroups
             * @description Retrieves a list of assignable users within the resource group that user belongs to.
             * @memberof GroupsAPI.prototype
             * @param {object} params - An object providing the affiliate that the current user belongs to.
             * @param {function} successHandler - A function that is 
             * called back upon success.
             * @param {function} [failureHandler] - An optional 
             * function that is called back upon failure. If none is specified,
             * the success callback is called with failure data. On failure 
             * however, the only valid fields returned are: 
             * <code>status, statusMessage, api</code> and <code>date</code>.
             * @throws (string) "missing.callback.exception"
             * @throws {} $http errors
             * @returns {object} A result object. 
             * <pre><code>
             * result {
             *      api: "adm::get::assignableusers",
             *      date: [Date object providing time call was made],
             *      status: '0',
             *      statusMessage: "adm.no.errors",
             *      assignableUsers: [Array of string elements]
             * };</pre></code>
             * @example 
             * function getAssignableUsers(){
             *     var param = {
             *         affiliate: $rootScope.credential.affiliate
             *     };
             *     groupsApi.getAssignableUsers(param, getAssignableUsersHandler);
             * }
             *
             * function getAssignableUsersHandler(result){
             *     if (result.status === '0'){
             *         $scope.assignableUsers = result.assignableUsers;
             *     } else {
             *         $scope.errorCode = result.status;
             *         $scope.errorMessage = result.statusMessage;
             *     }  
             * }
             */
            
            getAssignableUsers: function(params, successHandler, failureHandler) {
                // require a successHandler
                if (!successHandler) {
                    throw new Error("missing.callback.exception");
                }
                
                // if no failureHandler is defined, use successHandler as 
                // general callback
                if (!failureHandler) {
                    failureHandler = successHandler;
                }
                
                var result = get('assignableusers?', params);
                result.then(function (response) {
                    var x2js = new X2JS();
                    var jsonData = x2js.xml_str2json(response.data);
                    var assignableUsersData = {};
                    
                    assignableUsersData.date = new Date();
                    assignableUsersData.api = jsonData.adm_service_response.api;
                    assignableUsersData.status = jsonData.adm_service_response.error_response.response_code;
                    assignableUsersData.statusMessage = jsonData.adm_service_response.error_response.response_message;
                    
                    if (assignableUsersData.status === '0'){
                        var assignableUsers = jsonData.adm_service_response.response.assignable_user_list.userid;
                        if (assignableUsers && !Array.isArray(assignableUsers)) {
                            var tmp = [];
                            tmp.push(assignableUsers);
                            assignableUsers = tmp;
                        } else if (!assignableUsers) {
                            assignableUsers = [];
                        }

                        assignableUsersData.assignableUsers = assignableUsers;
                        successHandler(assignableUsersData);
                    } else {
                        failureHandler(assignableUsersData);
                    }
                },
                function (errorInfo) {
                    throw new Error(errorInfo.data);
                });
            },
            
            /** 
             * Retrieves a list of system group users.
             * @function 
             * @name getSystemGroupUsers
             * @description Retrieves a list of system group users.
             * @memberof GroupsAPI.prototype
             * @param {object} params - An object providing the system group.
             * @param {function} successHandler - A function that is 
             * called back upon success.
             * @param {function} [failureHandler] - An optional 
             * function that is called back upon failure. If none is specified,
             * the success callback is called with failure data. On failure 
             * however, the only valid fields returned are: 
             * <code>status, statusMessage, api</code> and <code>date</code>.
             * @throws (string) "missing.callback.exception"
             * @throws {} $http errors
             * @returns {object} A result object. 
             * <pre><code>
             * result {
             *      api: "adm::get::systemgroupusers",
             *      date: [Date object providing time call was made],
             *      status: '0',
             *      statusMessage: "adm.no.errors",
             *      systemGroupUsers: [Array of strings elements]
             * };</pre></code>
             * @example 
             * function getSystemGroupUsers(){
             *     var params = {
             *         groupname: $scope.systemGroup
             *     };
             *     groupsApi.getSystemGroupUsers(params, getSystemGroupUsersHandler);
             * }
             *
             * function getSystemGroupUsersHandler(result){
             *     if (result.status === '0'){
             *         $scope.systemGroupUsers = result.systemGroupUsers;
             *     } else {
             *         $scope.errorCode = result.status;
             *         $scope.errorMessage = result.statusMessage;
             *     }  
             * }
             */
            
            getSystemGroupUsers: function(params, successHandler, failureHandler) {
                // require a successHandler
                if (!successHandler) {
                    throw new Error("missing.callback.exception");
                }
                
                // if no failureHandler is defined, use successHandler as 
                // general callback
                if (!failureHandler) {
                    failureHandler = successHandler;
                }
                
                var result = get('systemgroupusers?', params);
                result.then(function (response) {
                    var x2js = new X2JS();
                    var jsonData = x2js.xml_str2json(response.data);
                    var systemGroupUsersData = {};
                    
                    systemGroupUsersData.date = new Date();
                    systemGroupUsersData.api = jsonData.adm_service_response.api;
                    systemGroupUsersData.status = jsonData.adm_service_response.error_response.response_code;
                    systemGroupUsersData.statusMessage = jsonData.adm_service_response.error_response.response_message;
                    
                    if (systemGroupUsersData.status === '0'){
                        var systemGroupUsers = jsonData.adm_service_response.response.assigned_user_list.userid;
                        if (systemGroupUsers && !Array.isArray(systemGroupUsers)) {
                            var tmp = [];
                            tmp.push(systemGroupUsers);
                            systemGroupUsers = tmp;
                        } else if (!systemGroupUsers) {
                            systemGroupUsers = [];
                        }

                        systemGroupUsersData.systemGroupUsers = systemGroupUsers;
                        successHandler(systemGroupUsersData);
                    } else {
                        failureHandler(systemGroupUsersData);
                    }
                },
                function (errorInfo) {
                    throw new Error(errorInfo.data);
                });
            },
            
            /** 
             * Retrieves a list of public group users.
             * @function 
             * @name getPublicGroupsUsers
             * @description Retrieves a list of public group users.
             * @memberof GroupsAPI.prototype
             * @param {object} params - An object providing the public group.
             * @param {function} successHandler - A function that is 
             * called back upon success.
             * @param {function} [failureHandler] - An optional 
             * function that is called back upon failure. If none is specified,
             * the success callback is called with failure data. On failure 
             * however, the only valid fields returned are: 
             * <code>status, statusMessage, api</code> and <code>date</code>.
             * @throws (string) "missing.callback.exception"
             * @throws {} $http errors
             * @returns {object} A result object. 
             * <pre><code>
             * result {
             *      status: ['0' for success, otherwise failure],
             *      statusMessage: [message indicating reason for status value],
             *      api: [the API that was called],
             *      publicGroupUsers: [an array of strings]
             * };</pre></code>
             * @example 
             * function getPublicGroupUsers(){
             *      var params = {
             *          groupname: $scope.publicGroup  
             *      };
             *      groupsApi.getPublicGroupUsers(params, getPublicGroupUsersHandler);
             *  }
             *
             *  function getPublicGroupUsersHandler(result){
             *      if (result.status === '0'){
             *          $scope.publicGroupUsers = result.publicGroupUsers;
             *      } else {
             *          $scope.errorCode = result.status;
             *          $scope.errorMessage = result.statusMessage;
             *      }
             *  }
             */
            
            getPublicGroupUsers: function(params, successHandler, failureHandler) {
                // require a successHandler
                if (!successHandler) {
                    throw new Error("missing.callback.exception");
                }
                
                // if no failureHandler is defined, use successHandler as 
                // general callback
                if (!failureHandler) {
                    failureHandler = successHandler;
                }
                
                var result = get('publicgroupusers?', params);
                result.then(function (response) {
                    var x2js = new X2JS();
                    var jsonData = x2js.xml_str2json(response.data);
                    var publicGroupUsersData = {};
                    
                    publicGroupUsersData.date = new Date();
                    publicGroupUsersData.api = jsonData.adm_service_response.api;
                    publicGroupUsersData.status = jsonData.adm_service_response.error_response.response_code;
                    publicGroupUsersData.statusMessage = jsonData.adm_service_response.error_response.response_message;
                    
                    if (publicGroupUsersData.status === '0'){
                        var publicGroupUsers = jsonData.adm_service_response.response.assigned_user_list.userid;
                        if (publicGroupUsers && !Array.isArray(publicGroupUsers)) {
                            var tmp = [];
                            tmp.push(publicGroupUsers);
                            publicGroupUsers = tmp;
                        } else if (!publicGroupUsers) {
                            publicGroupUsers = [];
                        }

                        publicGroupUsersData.publicGroupUsers = publicGroupUsers;
                        successHandler(publicGroupUsersData);
                    } else {
                        failureHandler(publicGroupUsersData);
                    }
                },
                function (errorInfo) {
                    throw new Error(errorInfo.data);
                });
            },
            
            /** 
             * Creates a new public group.
             * @function 
             * @name postAddPublicGroup
             * @description Creates a new public group.
             * @memberof GroupsAPI.prototype
             * @param {object} params - An object providing the name of the new public group. 
             * that will be set for deletion.
             * @param {function} successHandler - A function that is 
             * called back upon success.
             * @param {function} [failureHandler] - An optional 
             * function that is called back upon failure. If none is specified,
             * the success callback is called with failure data. On failure 
             * however, the only valid fields returned are: 
             * <code>status, statusMessage, api</code> and <code>date</code>.
             * @throws (string) "missing.callback.exception"
             * @throws {} $http errors
             * @returns {object} A result object. 
             * <pre><code>
             * result {
             *      status: ['0' for success, otherwise failure],
             *      statusMessage: [message indicating reason for status value],
             *      api: [the API that was called],
             * };</pre></code>
             * @example 
             * $scope.addPublicGroup = function(publicGroup) {
             *      var params = {
             *          groupname: publicGroup
             *      };
             *      groupsApi.postAddPublicGroup(params, addPublicGroupHandler);
             *  };
             *  
             *  function addPublicGroupHandler(result){
             *      if (result.status === '0'){
             *          groupsApi.getPublicGroups(getPublicGroupsHandler);
             *      } else {
             *          $scope.errorCode = result.status;
             *          $scope.errorMessage = result.statusMessage;
             *      } 
             *  }
             */
            
            postAddPublicGroup: function(params, successHandler, failureHandler) {
                // require a successHandler
                if (!successHandler) {
                    throw new Error("missing.callback.exception");
                }
                
                // if no failureHandler is defined, use successHandler as 
                // general callback
                if (!failureHandler) {
                    failureHandler = successHandler;
                }
                
                var result = post('publicgroups?', params);
                result.then(function (response) {
                    var x2js = new X2JS();
                    var jsonData = x2js.xml_str2json(response.data);
                    var response = {};
                    
                    response.date = new Date();
                    response.api = jsonData.adm_service_response.api;
                    response.status = jsonData.adm_service_response.error_response.response_code;
                    response.statusMessage = jsonData.adm_service_response.error_response.response_message;
                    
                    if (response.status === '0') {
                        successHandler(response);
                    } else {
                        failureHandler(response);
                    }
                },
                function (errorInfo) {
                    throw new Error(errorInfo.data);
                });
                
            },
            
            /** 
             * Adds a user to a public group.
             * @function 
             * @name postAddUserToPublicGroup
             * @description Adds a user to a public group.
             * @memberof GroupsAPI.prototype
             * @param {object} params - An object providing a public group and a user to added to that group.
             * @param {function} successHandler - A function that is 
             * called back upon success.
             * @param {function} [failureHandler] - An optional 
             * function that is called back upon failure. If none is specified,
             * the success callback is called with failure data. On failure 
             * however, the only valid fields returned are: 
             * <code>status, statusMessage, api</code> and <code>date</code>.
             * @throws (string) "missing.callback.exception"
             * @throws {} $http errors
             * @returns {object} A result object. 
             * <pre><code>
             * result {
             *      status: ['0' for success, otherwise failure],
             *      statusMessage: [message indicating reason for status value],
             *      api: [the API that was called],
             * };</pre></code>
             * @example 
             * $scope.addUserToPublicGroup = function(){
             *      var params = {
             *          userid: $scope.selectedPublicGroupUser,
             *          groupname: $scope.publicGroup
             *      };
             *      groupsApi.postAddUserToPublicGroup(params, addUserToPublicGroupHandler);
             *  };
             *
             *  function addUserToPublicGroupHandler(result){
             *      if (result.status === '0'){
             *          console.log("add user to public group");
             *      } else {
             *          $scope.errorCode = result.status;
             *          $scope.errorMessage = result.statusMessage;
             *      }
             *  }
             */
            
            postAddUserToPublicGroup: function(params, successHandler, failureHandler) {
                // require a successHandler
                if (!successHandler) {
                    throw new Error("missing.callback.exception");
                }
                
                // if no failureHandler is defined, use successHandler as 
                // general callback
                if (!failureHandler) {
                    failureHandler = successHandler;
                }
                
                var result = post('publicgroupuser?', params);
                result.then(function (response) {
                    var x2js = new X2JS();
                    var jsonData = x2js.xml_str2json(response.data);
                    var response = {};
                    
                    response.date = new Date();
                    response.api = jsonData.adm_service_response.api;
                    response.status = jsonData.adm_service_response.error_response.response_code;
                    response.statusMessage = jsonData.adm_service_response.error_response.response_message;
                    
                    if (response.status === '0') {
                        successHandler(response);
                    } else {
                        failureHandler(response);
                    }
                },
                function (errorInfo) {
                    throw new Error(errorInfo.data);
                });
                
            },
            
            /** 
             * Adds a user to a system group.
             * @function 
             * @name postAddUserToSystemGroup
             * @description Adds a user to a system group.
             * @memberof GroupsAPI.prototype
             * @param {object} params - An object providing a system group and a user to be added to that group.
             * @param {function} successHandler - A function that is 
             * called back upon success.
             * @param {function} [failureHandler] - An optional 
             * function that is called back upon failure. If none is specified,
             * the success callback is called with failure data. On failure 
             * however, the only valid fields returned are: 
             * <code>status, statusMessage, api</code> and <code>date</code>.
             * @throws (string) "missing.callback.exception"
             * @throws {} $http errors
             * @returns {object} A result object. 
             * <pre><code>
             * result {
             *      status: ['0' for success, otherwise failure],
             *      statusMessage: [message indicating reason for status value],
             *      api: [the API that was called],
             * };</pre></code>
             * @example 
             * $scope.addUserToSystemGroup = function(){
             *       var params = {
             *          userid: $scope.selectedSystemGroupUser,
             *          groupname: $scope.systemGroup
             *       };
             *       groupsApi.postAddUserToSystemGroup(params, addUserToSystemGroupHandler);
             *  };
             *
             *  function addUserToSystemGroupHandler(result){
             *      if (result.status === '0'){
             *          console.log("User added");
             *      } else {
             *          $scope.errorCode = result.status;
             *          $scope.errorMessage = result.statusMessage;
             *      }
             *  }
             */
            
            postAddUserToSystemGroup: function(params, successHandler, failureHandler) {
                // require a successHandler
                if (!successHandler) {
                    throw new Error("missing.callback.exception");
                }
                
                // if no failureHandler is defined, use successHandler as 
                // general callback
                if (!failureHandler) {
                    failureHandler = successHandler;
                }
                
                var result = post('systemgroupuser?', params);
                result.then(function (response) {
                    var x2js = new X2JS();
                    var jsonData = x2js.xml_str2json(response.data);
                    var response = {};
                    
                    response.date = new Date();
                    response.api = jsonData.adm_service_response.api;
                    response.status = jsonData.adm_service_response.error_response.response_code;
                    response.statusMessage = jsonData.adm_service_response.error_response.response_message;
                    
                    if (response.status === '0') {
                        successHandler(response);
                    } else {
                        failureHandler(response);
                    }
                },
                function (errorInfo) {
                    throw new Error(errorInfo.data);
                });
                
            }
             
        };
        
        function get(path, param) {
            return request("GET", path, param);
        }

        function post(path, param, data) {
            return request("POST", path, param, data);
        }

        function put(path, param, data) {
            return request("PUT", path, param, data);
        }

        function del(path, param) {
            return request("DELETE", path, param);
        }

        function request(verb, path, param, data) {
            var site = $rootScope.site;
            var token = null;
            if (validData($rootScope.credential) && validData($rootScope.credential.token)) {
                token = $rootScope.credential.token;
            }
            var req = {
                method: verb,
                url: url(site, token, path, param),
                headers: {
                    'Authorization': getAuthHeader()
                },
                data: validData(data) ? data : null
            };
            return $http(req);
        }

        function url(site, token, path, param) {
            var reqUrl = 'https://' + site + '/api/' + token + '/adm/';
            if (validData(path)) {
                reqUrl += path;
            }

            if (validData(param)) {
                reqUrl += $.param(param);
            }
            return reqUrl;
        }
        
        function validData(data) {
            return data !== undefined && data !== null;
        }

        function getAuthHeader() {
            return "";
        }
    }
    
}