//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

var inflection = require('inflection');
var request = require('request');
var Usergrid = {};
Usergrid.USERGRID_SDK_VERSION = '0.10.07';

//authentication type constants
var AUTH_CLIENT_ID = 'CLIENT_ID';
var AUTH_APP_USER = 'APP_USER';
var AUTH_NONE = 'NONE';

  Usergrid.Client = function(options) {
    //usergrid enpoint
    this.URI = options.URI || 'https://api.usergrid.com';

    //Find your Orgname and Appname in the Admin portal (http://apigee.com/usergrid)
    if (options.orgName) {
      this.set('orgName', options.orgName);
    }
    if (options.appName) {
      this.set('appName', options.appName);
    }

    //authentication data
    this.authType = options.authType || AUTH_NONE;
    this.clientId = options.clientId;
    this.clientSecret = options.clientSecret;
    this.token = options.token || null;

    //other options
    this.buildCurl = options.buildCurl || false;
    this.logging = options.logging || false;

    //timeout and callbacks
    this._callTimeout =  options.callTimeout || 30000; //default to 30 seconds
    this._callTimeoutCallback =  options.callTimeoutCallback || null;
    this.logoutCallback =  options.logoutCallback || null;
  };

  /*
  *  Main function for making requests to the API.  Can be called directly.
  *
  *  options object:
  *  `method` - http method (GET, POST, PUT, or DELETE), defaults to GET
  *  `qs` - object containing querystring values to be appended to the uri
  *  `body` - object containing entity body for POST and PUT requests
  *  `endpoint` - API endpoint, for example 'users/fred'
  *  `mQuery` - boolean, set to true if running management query, defaults to false
  *
  *  @method request
  *  @public
  *  @params {object} options
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  */
  Usergrid.Client.prototype.request = function (options, callback) {
    var self = this;
    var method = options.method || 'GET';
    var endpoint = options.endpoint;
    var body = options.body || {};
    var qs = options.qs || {};
    var mQuery = options.mQuery || false; //is this a query to the management endpoint?
    var orgName = this.get('orgName');
    var appName = this.get('appName');
    if(!mQuery && !orgName && !appName){
      if (typeof(this.logoutCallback) === 'function') {
        return this.logoutCallback(true, 'no_org_or_app_name_specified');
      }
    }
    var uri;
    if (mQuery) {
      uri = this.URI + '/' + endpoint;
    } else {
      uri = this.URI + '/' + orgName + '/' + appName + '/' + endpoint;
    }

    if (this.authType === AUTH_CLIENT_ID) {
      qs['client_id'] = this.clientId;
      qs['client_secret'] = this.clientSecret;
    } else if (this.authType === AUTH_APP_USER && self.getToken()) {
      qs['access_token'] = self.getToken();
    }

    if (this.logging) {
      console.log('calling: ' + method + ' ' + uri);
    }
    this._start = new Date().getTime();
    var callOptions = {
      method: method,
      uri: uri,
      json: body,
      qs: qs
    };
    request(callOptions, function (err, r, data) {

      r.body = r.body || {};
      data = data || {};

      if (self.buildCurl) {
        options.uri = r.request.uri.href;
        self.buildCurlCall(options);
      }
      self._end = new Date().getTime();
      if(r.statusCode === 200) {
        if (self.logging) {
          console.log('success (time: ' + self.calcTimeDiff() + '): ' + method + ' ' + uri);
        }
        callback(err, data);
      } else {
        err = true;
        data.statusCode = r.statusCode;
        if ((r.error === 'auth_expired_session_token') ||
          (r.error === 'auth_missing_credentials')   ||
          (r.error == 'auth_unverified_oath')       ||
          (r.error === 'expired_token')   ||
          (r.error === 'unauthorized')   ||
          (r.error === 'auth_invalid')) {
          //this error type means the user is not authorized. If a logout function is defined, call it
          var error = r.body.error;
          var errorDesc = r.body.error_description;
          if (self.logging) {
            console.log('Error (' + r.statusCode + ')(' + error + '): ' + errorDesc);
          }
          //if the user has specified a logout callback:
          if (typeof(self.logoutCallback) === 'function') {
            self.logoutCallback(err, data);
          } else  if (typeof(callback) === 'function') {
            callback(err, data);
          }
        } else {
          var error = r.body.error;
          var errorDesc = r.body.error_description;
          if (self.logging) {
            console.log('Error (' + r.statusCode + ')(' + error + '): ' + errorDesc);
          }
          if (typeof(callback) === 'function') {
            callback(err, data);
          }
        }
      }
    });
  };
  /*
   *  function for building asset urls
   *
   *  @method buildAssetURL
   *  @public
   *  @params {string} uuid
   *  @return {string} assetURL
   */
   Usergrid.Client.prototype.buildAssetURL = function(uuid) {
     var self = this;
     var qs = {};
     var assetURL = this.URI + '/' + this.orgName + '/' + this.appName + '/assets/' + uuid + '/data';

     if (self.getToken()) {
       qs['access_token'] = self.getToken();
     }

     //append params to the path
     var encoded_params = encodeParams(qs);
     if (encoded_params) {
       assetURL += "?" + encoded_params;
     }

     return assetURL;
   }

  /*
   *  Main function for creating new groups. Call this directly.
   *
   *  @method createGroup
   *  @public
   *  @params {string} path
   *  @param {function} callback
   *  @return {callback} callback(err, data)
   */
  Usergrid.Client.prototype.createGroup = function(options, callback) {
    var getOnExist = options.getOnExist || false;
    delete options.getOnExist;

    var options = {
      path: options.path,
      client: this,
      data:options
    }

    var group = new Usergrid.Group(options);
    group.fetch(function(err, data){
      var okToSave = (err && 'service_resource_not_found' === data.error || 'no_name_specified' === data.error || 'null_pointer' === data.error) || (!err && getOnExist);
      if (okToSave) {
        group.save(function(err, data){
          if (typeof(callback) === 'function') {
            callback(err, group);
          }
        });
      } else {
        if(typeof(callback) === 'function') {
          callback(err, group);
        }
      }
    });
  }

  /*
  *  Main function for creating new entities - should be called directly.
  *
  *  options object: options {data:{'type':'collection_type', 'key':'value'}, uuid:uuid}}
  *
  *  @method createEntity
  *  @public
  *  @params {object} options
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  */
  Usergrid.Client.prototype.createEntity = function (options, callback) {
    // todo: replace the check for new / save on not found code with simple save
    // when users PUT on no user fix is in place.
    /*
    var options = {
      client:this,
      data:options
    }
    var entity = new Usergrid.Entity(options);
    entity.save(function(err, data) {
      if (typeof(callback) === 'function') {
        callback(err, entity);
      }
    });
    */
    var getOnExist = options.getOnExist || false; //if true, will return entity if one already exists
    delete options.getOnExist;

    var options = {
      client:this,
      data:options
    }
    var entity = new Usergrid.Entity(options);
    entity.fetch(function(err, data) {
      //if the fetch doesn't find what we are looking for, or there is no error, do a save
      var okToSave = (err && 'service_resource_not_found' === data.error || 'no_name_specified' === data.error || 'null_pointer' === data.error) || (!err && getOnExist);
      if(okToSave) {
        entity.set(options.data); //add the data again just in case
        entity.save(function(err, data) {
          if (typeof(callback) === 'function') {
            callback(err, entity, data);
          }
        });
      } else {
        if (typeof(callback) === 'function') {
          callback(err, entity, data);
        }
      }
    });

  }

  /*
   *  Main function for getting existing entities - should be called directly.
   *
   *  You must supply a uuid or (username or name). Username only applies to users.
   *  Name applies to all custom entities
   *
   *  options object: options {data:{'type':'collection_type', 'name':'value', 'username':'value'}, uuid:uuid}}
   *
   *  @method createEntity
   *  @public
   *  @params {object} options
   *  @param {function} callback
   *  @return {callback} callback(err, data)
   */
  Usergrid.Client.prototype.getEntity = function (options, callback) {
    var options = {
      client:this,
      data:options
    }
    var entity = new Usergrid.Entity(options);
    entity.fetch(function(err, data) {
      if (typeof(callback) === 'function') {
        callback(err, entity, data);
      }
    });
  }

  /*
   *  Main function for restoring an entity from serialized data.
   *
   *  serializedObject should have come from entityObject.serialize();
   *
   *  @method restoreEntity
   *  @public
   *  @param {string} serializedObject
   *  @return {object} Entity Object
   */
  Usergrid.Client.prototype.restoreEntity = function (serializedObject) {
    var data = JSON.parse(serializedObject);
    var options = {
      client:this,
      data:data
    }
    var entity = new Usergrid.Entity(options);
    return entity;
  }

  /*
  *  Main function for creating new collections - should be called directly.
  *
  *  options object: options {client:client, type: type, qs:qs}
  *
  *  @method createCollection
  *  @public
  *  @params {object} options
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  */
  Usergrid.Client.prototype.createCollection = function (options, callback) {
    options.client = this;
    var collection = new Usergrid.Collection(options, function(err, data) {
      if (typeof(callback) === 'function') {
        callback(err, collection, data);
      }
    });
  }

  /*
   *  Main function for restoring a collection from serialized data.
   *
   *  serializedObject should have come from collectionObject.serialize();
   *
   *  @method restoreCollection
   *  @public
   *  @param {string} serializedObject
   *  @return {object} Collection Object
   */
  Usergrid.Client.prototype.restoreCollection = function (serializedObject) {
    var data = JSON.parse(serializedObject);
    data.client = this;
    var collection = new Usergrid.Collection(data);
    return collection;
  }

  /*
   *  Main function for retrieving a user's activity feed.
   *
   *  @method getFeedForUser
   *  @public
   *  @params {string} username
   *  @param {function} callback
   *  @return {callback} callback(err, data, activities)
   */
  Usergrid.Client.prototype.getFeedForUser = function(username, callback) {
    var options = {
      method: "GET",
      endpoint: "users/"+username+"/feed"
    }

    this.request(options, function(err, data){
      if(typeof(callback) === "function") {
        if(err) {
          callback(err);
        } else {
          callback(err, data, data.entities);
        }
      }
    });
  }

  /*
  *  Function for creating new activities for the current user - should be called directly.
  *
  *  //user can be any of the following: "me", a uuid, a username
  *  Note: the "me" alias will reference the currently logged in user (e.g. 'users/me/activties')
  *
  *  //build a json object that looks like this:
  *  var options =
  *  {
  *    "actor" : {
  *      "displayName" :"myusername",
  *      "uuid" : "myuserid",
  *      "username" : "myusername",
  *      "email" : "myemail",
  *      "picture": "http://path/to/picture",
  *      "image" : {
  *          "duration" : 0,
  *          "height" : 80,
  *          "url" : "http://www.gravatar.com/avatar/",
  *          "width" : 80
  *      },
  *    },
  *    "verb" : "post",
  *    "content" : "My cool message",
  *    "lat" : 48.856614,
  *    "lon" : 2.352222
  *  }
  *
  *  @method createEntity
  *  @public
  *  @params {string} user // "me", a uuid, or a username
  *  @params {object} options
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  */
  Usergrid.Client.prototype.createUserActivity = function (user, options, callback) {
    options.type = 'users/'+user+'/activities';
    var options = {
      client:this,
      data:options
    }
    var entity = new Usergrid.Entity(options);
    entity.save(function(err, data) {
      if (typeof(callback) === 'function') {
        callback(err, entity);
      }
    });
  }

  /*
   *  Function for creating user activities with an associated user entity.
   *
   *  user object:
   *  The user object passed into this function is an instance of Usergrid.Entity.
   *
   *  @method createUserActivityWithEntity
   *  @public
   *  @params {object} user
   *  @params {string} content
   *  @param {function} callback
   *  @return {callback} callback(err, data)
   */
  Usergrid.Client.prototype.createUserActivityWithEntity = function(user, content, callback) {
    var username = user.get("username");
    var options = {
      actor: {
        "displayName":username,
        "uuid":user.get("uuid"),
        "username":username,
        "email":user.get("email"),
        "picture":user.get("picture"),
        "image": {
          "duration":0,
          "height":80,
          "url":user.get("picture"),
          "width":80
         },
      },
      "verb":"post",
      "content":content };

    this.createUserActivity(username, options, callback);

  }

  /*
  *  A private method to get call timing of last call
  */
  Usergrid.Client.prototype.calcTimeDiff = function () {
   var time = this._end - this._start;
   return (time/1000).toFixed(2);
  }

  /*
   *  A public method to store the OAuth token for later use - uses localstorage if available
   *
   *  @method setToken
   *  @public
   *  @params {string} token
   *  @return none
   */
  Usergrid.Client.prototype.setToken = function (token) {
    this.set('token', token);
  }

  /*
   *  A public method to get the OAuth token
   *
   *  @method getToken
   *  @public
   *  @return {string} token
   */
  Usergrid.Client.prototype.getToken = function () {
    return this.get('token');
  }

  Usergrid.Client.prototype.setObject = function(key, value) {
    if (value) {
      value = JSON.stringify(value);
    }
    this.set(key, value);
  }

  Usergrid.Client.prototype.set = function (key, value) {
    var keyStore =  'apigee_' + key;
    this[key] = value;
    if(typeof(Storage)!=="undefined"){
      if (value) {
        localStorage.setItem(keyStore, value);
      } else {
        localStorage.removeItem(keyStore);
      }
    }
  }

  Usergrid.Client.prototype.getObject = function(key) {
    return JSON.parse(this.get(key));
  }

  Usergrid.Client.prototype.get = function (key) {
    var keyStore = 'apigee_' + key;
    if (this[key]) {
      return this[key];
    } else if(typeof(Storage)!=="undefined") {
      return localStorage.getItem(keyStore);
    }
    return null;
  }

  /*
   * A public facing helper method for signing up users
   *
   * @method signup
   * @public
   * @params {string} username
   * @params {string} password
   * @params {string} email
   * @params {string} name
   * @param {function} callback
   * @return {callback} callback(err, data)
   */
  Usergrid.Client.prototype.signup = function(username, password, email, name, callback) {
    var self = this;
    var options = {
      type:"users",
      username:username,
      password:password,
      email:email,
      name:name
    };

    this.createEntity(options, callback);
  }

  /*
  *
  *  A public method to log in an app user - stores the token for later use
  *
  *  @method login
  *  @public
  *  @params {string} username
  *  @params {string} password
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  */
  Usergrid.Client.prototype.login = function (username, password, callback) {
    var self = this;
    var options = {
      method:'POST',
      endpoint:'token',
      body:{
        username: username,
        password: password,
        grant_type: 'password'
      }
    };
    this.request(options, function(err, data) {
      var user = {};
      if (err && self.logging) {
        console.log('error trying to log user in');
      } else {
        var options = {
          client:self,
          data:data.user
        }
        user = new Usergrid.Entity(options);
        self.setToken(data.access_token);
        }
      if (typeof(callback) === 'function') {
        callback(err, data, user);
      }
    });
  }


  Usergrid.Client.prototype.reAuthenticateLite = function (callback) {
    var self = this;
    var options = {
      method:'GET',
      endpoint:'management/me',
      mQuery:true
    };
    this.request(options, function(err, response) {
      if (err && self.logging) {
        console.log('error trying to re-authenticate user');
      } else {

        //save the re-authed token and current email/username
        self.setToken(response.access_token);

      }
      if (typeof(callback) === 'function') {
        callback(err);
      }
    });
  }


  Usergrid.Client.prototype.reAuthenticate = function (email, callback) {
    var self = this;
    var options = {
      method:'GET',
      endpoint:'management/users/'+email,
      mQuery:true
    };
    this.request(options, function(err, response) {
      var organizations = {};
      var applications = {};
      var user = {};
      if (err && self.logging) {
        console.log('error trying to full authenticate user');
      } else {
        var data = response.data;
        self.setToken(data.token);
        self.set('email', data.email);

        //delete next block and corresponding function when iframes are refactored
        localStorage.setItem('accessToken', data.token);
        localStorage.setItem('userUUID', data.uuid);
        localStorage.setItem('userEmail', data.email);
        //end delete block


        var userData = {
          "username" : data.username,
          "email" : data.email,
          "name" : data.name,
          "uuid" : data.uuid
        }
        var options = {
          client:self,
          data:userData
        }
        user = new Usergrid.Entity(options);

        organizations = data.organizations;
        var org = '';
        try {
          //if we have an org stored, then use that one. Otherwise, use the first one.
          var existingOrg = self.get('orgName');
          org = (organizations[existingOrg])?organizations[existingOrg]:organizations[Object.keys(organizations)[0]];
          self.set('orgName', org.name);
        } catch(e) {
          err = true;
          if (self.logging) { console.log('error selecting org'); }
        } //should always be an org

        applications = self.parseApplicationsArray(org);
        self.selectFirstApp(applications);

        self.setObject('organizations', organizations);
        self.setObject('applications', applications);

      }
      if (typeof(callback) === 'function') {
        callback(err, data, user, organizations, applications);
      }
    });
  }

  /*
  *  A public method to log in an app user with facebook - stores the token for later use
  *
  *  @method loginFacebook
  *  @public
  *  @params {string} username
  *  @params {string} password
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  */
  Usergrid.Client.prototype.loginFacebook = function (facebookToken, callback) {
    var self = this;
    var options = {
      method:'GET',
      endpoint:'auth/facebook',
      qs:{
        fb_access_token: facebookToken
      }
    };
    this.request(options, function(err, data) {
      var user = {};
      if (err && self.logging) {
        console.log('error trying to log user in');
      } else {
        var options = {
          client: self,
          data: data.user
        }
        user = new Usergrid.Entity(options);
        self.setToken(data.access_token);
      }
      if (typeof(callback) === 'function') {
        callback(err, data, user);
      }
    });
  }

  /*
  *  A public method to get the currently logged in user entity
  *
  *  @method getLoggedInUser
  *  @public
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  */
  Usergrid.Client.prototype.getLoggedInUser = function (callback) {
    if (!this.getToken()) {
      callback(true, null, null);
    } else {
      var self = this;
      var options = {
        method:'GET',
        endpoint:'users/me'
      };
      this.request(options, function(err, data) {
        if (err) {
          if (self.logging) {
            console.log('error trying to log user in');
          }
          if (typeof(callback) === 'function') {
            callback(err, data, null);
          }
        } else {
          var options = {
            client:self,
            data:data.entities[0]
          }
          var user = new Usergrid.Entity(options);
          if (typeof(callback) === 'function') {
            callback(err, data, user);
          }
        }
      });
    }
  }

  /*
  *  A public method to test if a user is logged in - does not guarantee that the token is still valid,
  *  but rather that one exists
  *
  *  @method isLoggedIn
  *  @public
  *  @return {boolean} Returns true the user is logged in (has token and uuid), false if not
  */
  Usergrid.Client.prototype.isLoggedIn = function () {
    if (this.getToken()) {
      return true;
    }
    return false;
  }

  /*
  *  A public method to log out an app user - clears all user fields from client
  *
  *  @method logout
  *  @public
  *  @return none
  */
  Usergrid.Client.prototype.logout = function () {
    this.setToken(null);
  }

  /*
  *  A private method to build the curl call to display on the command line
  *
  *  @method buildCurlCall
  *  @private
  *  @param {object} options
  *  @return {string} curl
  */
  Usergrid.Client.prototype.buildCurlCall = function (options) {
    var curl = 'curl';
    var method = (options.method || 'GET').toUpperCase();
    var body = options.body || {};
    var uri = options.uri;

    //curl - add the method to the command (no need to add anything for GET)
    if (method === 'POST') {curl += ' -X POST'; }
    else if (method === 'PUT') { curl += ' -X PUT'; }
    else if (method === 'DELETE') { curl += ' -X DELETE'; }
    else { curl += ' -X GET'; }

    //curl - append the path
    curl += ' ' + uri;

    //curl - add the body
    body = JSON.stringify(body)//only in node module
    if (body !== '"{}"' && method !== 'GET' && method !== 'DELETE') {
      //curl - add in the json obj
      curl += " -d '" + body + "'";
    }

    //log the curl command to the console
    console.log(curl);

    return curl;
  }

  Usergrid.Client.prototype.getDisplayImage = function (email, picture, size) {
    try {
      if (picture) {
        return picture;
      }
      var size = size || 50;
      if (email.length) {
        return 'https://secure.gravatar.com/avatar/' + MD5(email) + '?s=' + size + encodeURI("&d=https://apigee.com/usergrid/images/user_profile.png");
      } else {
        return 'https://apigee.com/usergrid/images/user_profile.png';
      }
    } catch(e) {
      return 'https://apigee.com/usergrid/images/user_profile.png';
    }
  }

  /*
  *  A class to Model a Usergrid Entity.
  *  Set the type and uuid of entity in the 'data' json object
  *
  *  @constructor
  *  @param {object} options {client:client, data:{'type':'collection_type', uuid:'uuid', 'key':'value'}}
  */
  Usergrid.Entity = function(options) {
    if (options) {
      this._data = options.data || {};
      this._client = options.client || {};
    }
  };

  /*
   *  returns a serialized version of the entity object
   *
   *  Note: use the client.restoreEntity() function to restore
   *
   *  @method serialize
   *  @return {string} data
   */
  Usergrid.Entity.prototype.serialize = function () {
    return JSON.stringify(this._data);
  }

  /*
  *  gets a specific field or the entire data object. If null or no argument
  *  passed, will return all data, else, will return a specific field
  *
  *  @method get
  *  @param {string} field
  *  @return {string} || {object} data
  */
  Usergrid.Entity.prototype.get = function (field) {
    if (field) {
      return this._data[field];
    } else {
      return this._data;
    }
  }

  /*
  *  adds a specific key value pair or object to the Entity's data
  *  is additive - will not overwrite existing values unless they
  *  are explicitly specified
  *
  *  @method set
  *  @param {string} key || {object}
  *  @param {string} value
  *  @return none
  */
  Usergrid.Entity.prototype.set = function (key, value) {
    if (typeof key === 'object') {
      for(var field in key) {
        this._data[field] = key[field];
      }
    } else if (typeof key === 'string') {
      if (value === null) {
        delete this._data[key];
      } else {
        this._data[key] = value;
      }
    } else {
      this._data = {};
    }
  }

  /*
  *  Saves the entity back to the database
  *
  *  @method save
  *  @public
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  */
  Usergrid.Entity.prototype.save = function (callback) {
    var type = this.get('type');
    var method = 'POST';
    if (isUUID(this.get('uuid'))) {
      method = 'PUT';
      type += '/' + this.get('uuid');
    }

    //update the entity
    var self = this;
    var data = {};
    var entityData = this.get();
    var password = this.get('password');
    var oldpassword = this.get('oldpassword');
    var newpassword = this.get('newpassword');
    //remove system specific properties
    for (var item in entityData) {
      if (item === 'metadata' || item === 'created' || item === 'modified' ||
          item === 'oldpassword' || item === 'newpassword' || //old and new pw not added to data
      item === 'type' || item === 'activated' || item === 'uuid') {
      continue;
    }
      data[item] = entityData[item];
    }
    var options =  {
      method:method,
      endpoint:type,
      body:data
    };
    //save the entity first
    this._client.request(options, function (err, retdata) {
      //clear out pw info if present
      self.set('password', null);
      self.set('oldpassword', null);
      self.set('newpassword', null);
      if (err && self._client.logging) {
        console.log('could not save entity');
        if (typeof(callback) === 'function') {
          return callback(err, retdata, self);
        }
      } else {
        if (retdata.entities) {
          if (retdata.entities.length) {
            var entity = retdata.entities[0];
            self.set(entity);
            var path = retdata.path;
            //for connections, API returns type
            while (path.substring(0, 1) === "/") {
              path = path.substring(1);
            }
            self.set('type', path);
          }
        }
        //if this is a user, update the password if it has been specified;
        var needPasswordChange = ((self.get('type') === 'user' || self.get('type') === 'users') && oldpassword && newpassword);
        if (needPasswordChange) {
          //Note: we have a ticket in to change PUT calls to /users to accept the password change
          //      once that is done, we will remove this call and merge it all into one
          var pwdata = {};
          pwdata.oldpassword = oldpassword;
          pwdata.newpassword = newpassword;
          var options = {
            method:'PUT',
            endpoint:type+'/password',
            body:pwdata
          }
          self._client.request(options, function (err, data) {
            if (err && self._client.logging) {
              console.log('could not update user');
            }
            //remove old and new password fields so they don't end up as part of the entity object
            self.set('oldpassword', null);
            self.set('newpassword', null);
            if (typeof(callback) === 'function') {
              callback(err, data, self);
            }
          });
        } else if (typeof(callback) === 'function') {
          callback(err, retdata, self);
        }
      }
    });
  }

  /*
  *  refreshes the entity by making a GET call back to the database
  *
  *  @method fetch
  *  @public
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  */
  Usergrid.Entity.prototype.fetch = function (callback) {
    var type = this.get('type');
    var self = this;

  //Check for an entity type, then if a uuid is available, use that, otherwise, use the name
  try {
    if (type === undefined) {
      throw 'cannot fetch entity, no entity type specified'
    } else if (this.get('uuid')) {
      type += '/' + this.get('uuid');
    } else if (type === 'users' && this.get('username')) {
      type += '/' + this.get('username');
    } else if (this.get('name')) {
      type += '/' + encodeURIComponent(this.get('name'));
    } else if (typeof(callback) === 'function') {
      throw 'no_name_specified';
    }
  } catch (e) {
    if (self._client.logging) {
      console.log(e);
    }
    return callback(true, {
      error: e
    }, self);
  }
    var options = {
      method:'GET',
      endpoint:type
    };
    this._client.request(options, function (err, data) {
      if (err && self._client.logging) {
        console.log('could not get entity');
      } else {
        if (data.user) {
          self.set(data.user);
          self._json = JSON.stringify(data.user, null, 2);
        } else if (data.entities) {
          if (data.entities.length) {
            var entity = data.entities[0];
            self.set(entity);
          }
        }
      }
      if (typeof(callback) === 'function') {
        callback(err, data, self);
      }
    });
  }

  /*
  *  deletes the entity from the database - will only delete
  *  if the object has a valid uuid
  *
  *  @method destroy
  *  @public
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  *
  */
  Usergrid.Entity.prototype.destroy = function (callback) {
    var self = this;
    var type = this.get('type');
    var id = this.getEntityId(this);
    if (!id) {
      if (typeof(callback) === 'function') {
        var error = 'Error trying to delete object - no uuid or name specified.';
        if (self._client.logging) {
          console.log(error);
        }
        return callback(true, error);
      }
    }
    type += '/' + this.get('uuid');
    var options = {
      method:'DELETE',
      endpoint:type
    };
    this._client.request(options, function (err, data) {
      if (err && self._client.logging) {
        console.log('entity could not be deleted');
      } else {
        self.set(null);
      }
      if (typeof(callback) === 'function') {
        callback(err, data);
      }
    });
  }

  /*
  *  connects one entity to another
  *
  *  @method connect
  *  @public
  *  @param {string} connection
  *  @param {object} entity
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  *
  */
  Usergrid.Entity.prototype.connect = function (connection, entity, callback) {

    var self = this;

    //connectee info
    var connecteeType = entity.get('type');
    var connectee = this.getEntityId(entity);
    if (!connectee) {
      if (typeof(callback) === 'function') {
        var error = 'Error trying to connect object - no uuid specified.';
        if (self._client.logging) {
          console.log(error);
        }
        callback(true, error);
      }
      return;
    }

    //connector info
    var connectorType = this.get('type');
    var connector = this.getEntityId(this);
    if (!connector) {
      if (typeof(callback) === 'function') {
        var error = 'Error in connect - no uuid specified.';
        if (self._client.logging) {
          console.log(error);
        }
        callback(true, error);
      }
      return;
    }

    var endpoint = connectorType + '/' + connector + '/' + connection + '/' + connecteeType + '/' + connectee;
    var options = {
      method:'POST',
      endpoint:endpoint
    };
    this._client.request(options, function (err, data) {
      if (err && self._client.logging) {
        console.log('entity could not be connected');
      }
      if (typeof(callback) === 'function') {
        callback(err, data);
      }
    });
  }

  /*
  *  returns a unique identifier for an entity
  *
  *  @method connect
  *  @public
  *  @param {object} entity
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  *
  */
  Usergrid.Entity.prototype.getEntityId = function (entity) {
    return entity.get('uuid') || entity.get('username') || entity.get('name') || false;
  }

  /*
  *  gets an entities connections
  *
  *  @method getConnections
  *  @public
  *  @param {string} connection
  *  @param {opts} options (actually, just options.qs for now)
  *  @param {function} callback
  *  @return {callback} callback(err, data, connections)
  *
  */
  Usergrid.Entity.prototype.getConnections = function (connection, opts, callback) {

    if (typeof(opts) == "function") { callback = opts; opts = undefined; }

    var self = this;

    //connector info
    var connectorType = inflection.pluralize(this.get('type'));
    var connector = this.getEntityId(this);
    if (!connector) {
      if (typeof(callback) === 'function') {
        var error = 'Error in getConnections - no uuid specified.';
        if (self._client.logging) {
          console.log(error);
        }
        callback(true, error);
      }
      return;
    }

    var endpoint = connectorType + '/' + connector + '/' + connection + '/';
    var options = {
      method:'GET',
      endpoint:endpoint
    };
    if (opts && opts.qs) { options.qs = opts.qs; }
    this._client.request(options, function (err, data) {
      if (err && self._client.logging) {
        console.log('entity connections could not be retrieved');
      }

      self[connection] = {};

      var length = data.entities.length;
      for (var i=0;i<length;i++)
      {
        if (data.entities[i].type === 'user'){
          self[connection][data.entities[i].username] = data.entities[i];
        } else {
          self[connection][data.entities[i].name] = data.entities[i];
        }
      }

      if (typeof(callback) === 'function') {
        callback(err, data, data.entities);
      }
    });

  }

  Usergrid.Entity.prototype.getGroups = function (callback) {

    var self = this;

    var endpoint = 'users' + '/' + this.get('uuid') + '/groups' ;
    var options = {
      method:'GET',
      endpoint:endpoint
    };
    this._client.request(options, function (err, data) {
      if (err && self._client.logging) {
        console.log('entity could not be connected');
      }

      self['groups'] = data.entities;

      if (typeof(callback) === 'function') {
        callback(err, data, data.entities);
      }
    });

  }

  Usergrid.Entity.prototype.getActivities = function (callback) {

    var self = this;

    var endpoint = this.get('type') + '/' + this.get('uuid') + '/activities' ;
    var options = {
      method:'GET',
      endpoint:endpoint
    };
    this._client.request(options, function (err, data) {
      if (err && self._client.logging) {
        console.log('entity could not be connected');
      }

      for(entity in data.entities) {
        data.entities[entity].createdDate = (new Date(data.entities[entity].created)).toUTCString();
      }

      self['activities'] = data.entities;

      if (typeof(callback) === 'function') {
        callback(err, data, data.entities);
      }
    });

  }

  Usergrid.Entity.prototype.getFollowing = function (callback) {

    var self = this;

    var endpoint = 'users' + '/' + this.get('uuid') + '/following' ;
    var options = {
      method:'GET',
      endpoint:endpoint
    };
    this._client.request(options, function (err, data) {
      if (err && self._client.logging) {
        console.log('could not get user following');
      }

      for(entity in data.entities) {
        data.entities[entity].createdDate = (new Date(data.entities[entity].created)).toUTCString();
        var image = self._client.getDisplayImage(data.entities[entity].email, data.entities[entity].picture);
        data.entities[entity]._portal_image_icon =  image;
      }

      self['following'] = data.entities;

      if (typeof(callback) === 'function') {
        callback(err, data, data.entities);
      }
    });

  }


  Usergrid.Entity.prototype.getFollowers = function (callback) {

    var self = this;

    var endpoint = 'users' + '/' + this.get('uuid') + '/followers' ;
    var options = {
      method:'GET',
      endpoint:endpoint
    };
    this._client.request(options, function (err, data) {
      if (err && self._client.logging) {
        console.log('could not get user followers');
      }

      for(entity in data.entities) {
        data.entities[entity].createdDate = (new Date(data.entities[entity].created)).toUTCString();
        var image = self._client.getDisplayImage(data.entities[entity].email, data.entities[entity].picture);
        data.entities[entity]._portal_image_icon =  image;
      }

      self['followers'] = data.entities;

      if (typeof(callback) === 'function') {
        callback(err, data, data.entities);
      }
    });

  }

  Usergrid.Entity.prototype.getRoles = function (callback) {

    var self = this;

    var endpoint = this.get('type') + '/' + this.get('uuid') + '/roles' ;
    var options = {
      method:'GET',
      endpoint:endpoint
    };
    this._client.request(options, function (err, data) {
      if (err && self._client.logging) {
        console.log('could not get user roles');
      }

      self['roles'] = data.entities;

      if (typeof(callback) === 'function') {
        callback(err, data, data.entities);
      }
    });

  }

  Usergrid.Client.prototype.createRole = function(roleName, permissions, callback) {

      var self = this;
      var options = {
          type: 'role',
          name: roleName
      };

      this.createEntity(options, function(err, entity, response) {
          if (err) {
              callback (err, response, self);
          } else {
              entity.assignPermissions(permissions, function (err, data) {
                  if (err) {
                      callback (err, response, self);
                  } else {
                      callback (err, data, data.data);
                  }
              })
          }
      });

  };
  Usergrid.Entity.prototype.assignRole = function(roleName, callback) {

      var self = this;
      var type = self.get('type');
      var collection = type + 's';
      var entityID;

      if (type == 'user' && this.get('username') != null) {
          entityID = self.get('username');
      } else if (type == 'group' && this.get('name') != null) {
          entityID = self.get('name');
      } else if (this.get('uuid') != null) {
          entityID = self.get('uuid');
      }

      if (type != 'users' && type != 'groups') {
          callback ('entity must be a group or user', null, this);
      }

      var endpoint = 'roles/' + roleName + '/' + collection + '/' + entityID;
      var options = {
          method: 'POST',
          endpoint: endpoint
      };

      this._client.request(options, function(err, response) {
          if (err) {
              console.log('Could not assign role.');
          }
          callback (err, response, self);
      });

  };

  Usergrid.Entity.prototype.removeRole = function(roleName, callback) {

      var self = this;
      var type = self.get('type');
      var collection = type + 's';
      var entityID;

      if (type == 'user' && this.get('username') != null) {
          entityID = this.get('username');
      } else if (type == 'group' && this.get('name') != null) {
          entityID = this.get('name');
      } else if (this.get('uuid') != null) {
          entityID = this.get('uuid');
      }

      if (type != 'users' && type != 'groups') {
          callback ('entity must be a group or user', null, this);
      }

      var endpoint = 'roles/' + roleName + '/' + collection + '/' + entityID;
      var options = {
          method: 'DELETE',
          endpoint: endpoint
      };

      this._client.request(options, function(err, response) {
          if (err) {
              console.log('Could not assign role.');
          }
          callback (err, response, self);
      });

  };

  Usergrid.Entity.prototype.assignPermissions = function(permissions, callback) {
      var self = this;
      var entityID;
      var type = this.get("type");

      if (type != 'user' && type != 'users' && type != 'group' && type != 'groups') {
          callback( 'entity must be a group or user', null, this);
      }

      if (type == 'user' && this.get("username") != null) {
          entityID = this.get("username");
      } else if (type == 'group' && this.get("name") != null) {
          entityID = this.get("name");
      } else if (this.get("uuid") != null) {
          entityID = this.get("uuid");
      }

      var endpoint = type + "/" + entityID + "/permissions";
      var options = {
          method: "POST",
          endpoint: endpoint,
          body: {
              'permission': permissions
          }
      };
      this._client.request(options, function(err, data) {
          if (err && self._client.logging) {
              console.log("could not assign permissions");
          }
          callback (err, data, data.data);
      });
  };

  Usergrid.Entity.prototype.removePermissions = function(permissions, callback) {
      var self = this;
      var entityID;
      var type = this.get("type");

      if (type != 'user' && type != 'users' && type != 'group' && type != 'groups') {
          callback ('entity must be a group or user', null, this);
      }

      if (type == 'user' && this.get("username") != null) {
          entityID = this.get("username");
      } else if (type == 'group' && this.get("name") != null) {
          entityID = this.get("name");
      } else if (this.get("uuid") != null) {
          entityID = this.get("uuid");
      }

      var endpoint = type + "/" + entityID + "/permissions";
      var options = {
          method: "DELETE",
          endpoint: endpoint,
          qs: {
              'permission': permissions
          }
      };
      this._client.request(options, function(err, data) {
          if (err && self._client.logging) {
              console.log("could not remove permissions");
          }
          callback (err, data, data.params.permission);
      });
  };
  Usergrid.Entity.prototype.getPermissions = function (callback) {

    var self = this;

    var endpoint = this.get('type') + '/' + this.get('uuid') + '/permissions' ;
    var options = {
      method:'GET',
      endpoint:endpoint
    };
    this._client.request(options, function (err, data) {
      if (err && self._client.logging) {
        console.log('could not get user permissions');
      }

      var permissions = [];
      if (data.data) {
        var perms = data.data;
        var count = 0;

        for (var i in perms) {
          count++;
          var perm = perms[i];
          var parts = perm.split(':');
          var ops_part = "";
          var path_part = parts[0];

          if (parts.length > 1) {
            ops_part = parts[0];
            path_part = parts[1];
          }

          ops_part.replace("*", "get,post,put,delete")
          var ops = ops_part.split(',');
          var ops_object = {}
          ops_object['get'] = 'no';
          ops_object['post'] = 'no';
          ops_object['put'] = 'no';
          ops_object['delete'] = 'no';
          for (var j in ops) {
            ops_object[ops[j]] = 'yes';
          }

          permissions.push( {operations : ops_object, path : path_part, perm : perm});
        }
      }

      self['permissions'] = permissions;

      if (typeof(callback) === 'function') {
        callback(err, data, data.entities);
      }
    });

  }

  /*
  *  disconnects one entity from another
  *
  *  @method disconnect
  *  @public
  *  @param {string} connection
  *  @param {object} entity
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  *
  */
  Usergrid.Entity.prototype.disconnect = function (connection, entity, callback) {

    var self = this;

    //connectee info
    var connecteeType = entity.get('type');
    var connectee = this.getEntityId(entity);
    if (!connectee) {
      if (typeof(callback) === 'function') {
        var error = 'Error trying to delete object - no uuid specified.';
        if (self._client.logging) {
          console.log(error);
        }
        callback(true, error);
      }
      return;
    }

    //connector info
    var connectorType = this.get('type');
    var connector = this.getEntityId(this);
    if (!connector) {
      if (typeof(callback) === 'function') {
        var error = 'Error in connect - no uuid specified.';
        if (self._client.logging) {
          console.log(error);
        }
        callback(true, error);
      }
      return;
    }

    var endpoint = connectorType + '/' + connector + '/' + connection + '/' + connecteeType + '/' + connectee;
    var options = {
      method:'DELETE',
      endpoint:endpoint
    };
    this._client.request(options, function (err, data) {
      if (err && self._client.logging) {
        console.log('entity could not be disconnected');
      }
      if (typeof(callback) === 'function') {
        callback(err, data);
      }
    });
  }

/*
 *  calls delete on the database w/ the passed query
 *
 *  @method delete
 *  @param {opts} options containing query (include options.qs)
 *  @param {function} callback
 *  @return {callback} callback(err, data)
 *
 */
Usergrid.Client.prototype.delete = function(opts, callback) {
  if (typeof(opts) == "function") { callback = opts; opts = undefined; }

  if (!opts.qs.q) { opts.qs.q = '*'; }

  var options = {
    method: 'DELETE',
    endpoint: opts.type,
    qs: opts.qs
  };
  var self = this;
  this.request(options, function (err, data) {
    if (err && self.logging) {
      console.log('entities could not be deleted');
    }
    if (typeof(callback) === 'function') {
      callback(err, data);
    }
  });
};

  /*
  *  The Collection class models Usergrid Collections.  It essentially
  *  acts as a container for holding Entity objects, while providing
  *  additional funcitonality such as paging, and saving
  *
  *  @constructor
  *  @param {string} options - configuration object
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  */
  Usergrid.Collection = function(options, callback) {

    if (options) {
      this._client = options.client;
      this._type = options.type;
      this.qs = options.qs || {};

      //iteration
      this._list = options.list || [];
      this._iterator = options.iterator || -1; //first thing we do is increment, so set to -1

      //paging
      this._previous = options.previous || [];
      this._next = options.next || null;
      this._cursor = options.cursor || null;

      //restore entities if available
      if (options.list) {
        var count = options.list.length;
        for(var i=0;i<count;i++){
          //make new entity with
          var entity = this._client.restoreEntity(options.list[i]);
          this._list[i] = entity;
        }
      }
    }
    if (callback) {
      //populate the collection
      this.fetch(callback);
    }

  }


  /*
   *  gets the data from the collection object for serialization
   *
   *  @method serialize
   *  @return {object} data
   */
  Usergrid.Collection.prototype.serialize = function () {

    //pull out the state from this object and return it
    var data = {}
    data.type = this._type;
    data.qs = this.qs;
    data.iterator = this._iterator;
    data.previous = this._previous;
    data.next = this._next;
    data.cursor = this._cursor;

    this.resetEntityPointer();
    var i=0;
    data.list = [];
    while(this.hasNextEntity()) {
      var entity = this.getNextEntity();
      data.list[i] = entity.serialize();
      i++;
    }

    data = JSON.stringify(data);
    return data;
  }

  Usergrid.Collection.prototype.addCollection = function (collectionName, options, callback) {
    self = this;
    options.client = this._client;
    var collection = new Usergrid.Collection(options, function(err, data) {
      if (typeof(callback) === 'function') {

        collection.resetEntityPointer();
        while(collection.hasNextEntity()) {
          var user = collection.getNextEntity();
          var email = user.get('email');
          var image = self._client.getDisplayImage(user.get('email'), user.get('picture'));
          user._portal_image_icon = image;
        }

        self[collectionName] = collection;
        callback(err, collection);
      }
    });
  }

  /*
  *  Populates the collection from the server
  *
  *  @method fetch
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  */
  Usergrid.Collection.prototype.fetch = function (callback) {
    var self = this;
    var qs = this.qs;

    //add in the cursor if one is available
    if (this._cursor) {
      qs.cursor = this._cursor;
    } else {
      delete qs.cursor;
    }
    var options = {
      method:'GET',
      endpoint:this._type,
      qs:this.qs
    };
    this._client.request(options, function (err, data) {
      if(err && self._client.logging) {
       console.log('error getting collection');
      } else {
        //save the cursor if there is one
        var cursor = data.cursor || null;
        self.saveCursor(cursor);
        if (data.entities) {
          self.resetEntityPointer();
          var count = data.entities.length;
          //save entities locally
          self._list = []; //clear the local list first
          for (var i=0;i<count;i++) {
            var uuid = data.entities[i].uuid;
            if (uuid) {
              var entityData = data.entities[i] || {};
              self._baseType = data.entities[i].type; //store the base type in the collection
              entityData.type = self._type;//make sure entities are same type (have same path) as parent collection.
              var entityOptions = {
                type:self._type,
                client:self._client,
                uuid:uuid,
                data:entityData
              };

              var ent = new Usergrid.Entity(entityOptions);
              ent._json = JSON.stringify(entityData, null, 2);
              var ct = self._list.length;
              self._list[ct] = ent;
            }
          }
        }
      }
      if (typeof(callback) === 'function') {
        callback(err, data);
      }
    });
  }

  /*
  *  Adds a new Entity to the collection (saves, then adds to the local object)
  *
  *  @method addNewEntity
  *  @param {object} entity
  *  @param {function} callback
  *  @return {callback} callback(err, data, entity)
  */
  Usergrid.Collection.prototype.addEntity = function (options, callback) {
    var self = this;
    options.type = this._type;

    //create the new entity
    this._client.createEntity(options, function (err, entity) {
      if (!err) {
        //then add the entity to the list
        var count = self._list.length;
        self._list[count] = entity;
      }
      if (typeof(callback) === 'function') {
        callback(err, entity);
      }
    });
  }

  Usergrid.Collection.prototype.addExistingEntity = function (entity) {
    //entity should already exist in the db, so just add it to the list
    var count = this._list.length;
    this._list[count] = entity;
  }

  /*
  *  Removes the Entity from the collection, then destroys the object on the server
  *
  *  @method destroyEntity
  *  @param {object} entity
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  */
  Usergrid.Collection.prototype.destroyEntity = function (entity, callback) {
    var self = this;
    entity.destroy(function(err, data) {
      if (err) {
        if (self._client.logging) {
          console.log('could not destroy entity');
        }
        if (typeof(callback) === 'function') {
          callback(err, data);
        }
      } else {
        //destroy was good, so repopulate the collection
        self.fetch(callback);
      }
    });
    //remove entity from the local store
    this.removeEntity(entity);
  }


  Usergrid.Collection.prototype.removeEntity = function (entity) {
    var uuid = entity.get('uuid');
    for (key in this._list) {
      var listItem = this._list[key];
      if (listItem.get('uuid') === uuid) {
        return this._list.splice(key, 1);
      }
    }
    return false;
  }

  /*
  *  Looks up an Entity by UUID
  *
  *  @method getEntityByUUID
  *  @param {string} UUID
  *  @param {function} callback
  *  @return {callback} callback(err, data, entity)
  */
  Usergrid.Collection.prototype.getEntityByUUID = function (uuid, callback) {

    for (key in this._list) {
      var listItem = this._list[key];
      if (listItem.get('uuid') === uuid) {
        return listItem;
      }
    }

    //get the entity from the database
    var options = {
      data: {
        type: this._type,
        uuid:uuid
      },
      client: this._client
    }
    var entity = new Usergrid.Entity(options);
    entity.fetch(callback);
  }

  /*
  *  Returns the first Entity of the Entity list - does not affect the iterator
  *
  *  @method getFirstEntity
  *  @return {object} returns an entity object
  */
  Usergrid.Collection.prototype.getFirstEntity = function () {
    var count = this._list.length;
    if (count > 0) {
      return this._list[0];
    }
    return null;
  }

  /*
  *  Returns the last Entity of the Entity list - does not affect the iterator
  *
  *  @method getLastEntity
  *  @return {object} returns an entity object
  */
  Usergrid.Collection.prototype.getLastEntity = function () {
    var count = this._list.length;
    if (count > 0) {
      return this._list[count-1];
    }
    return null;
  }

  /*
  *  Entity iteration -Checks to see if there is a "next" entity
  *  in the list.  The first time this method is called on an entity
  *  list, or after the resetEntityPointer method is called, it will
  *  return true referencing the first entity in the list
  *
  *  @method hasNextEntity
  *  @return {boolean} true if there is a next entity, false if not
  */
  Usergrid.Collection.prototype.hasNextEntity = function () {
    var next = this._iterator + 1;
    var hasNextElement = (next >=0 && next < this._list.length);
    if(hasNextElement) {
      return true;
    }
    return false;
  }

  /*
  *  Entity iteration - Gets the "next" entity in the list.  The first
  *  time this method is called on an entity list, or after the method
  *  resetEntityPointer is called, it will return the,
  *  first entity in the list
  *
  *  @method hasNextEntity
  *  @return {object} entity
  */
  Usergrid.Collection.prototype.getNextEntity = function () {
    this._iterator++;
    var hasNextElement = (this._iterator >= 0 && this._iterator <= this._list.length);
    if(hasNextElement) {
      return this._list[this._iterator];
    }
    return false;
  }

  /*
  *  Entity iteration - Checks to see if there is a "previous"
  *  entity in the list.
  *
  *  @method hasPrevEntity
  *  @return {boolean} true if there is a previous entity, false if not
  */
  Usergrid.Collection.prototype.hasPrevEntity = function () {
    var previous = this._iterator - 1;
    var hasPreviousElement = (previous >=0 && previous < this._list.length);
    if(hasPreviousElement) {
      return true;
    }
    return false;
  }

  /*
  *  Entity iteration - Gets the "previous" entity in the list.
  *
  *  @method getPrevEntity
  *  @return {object} entity
  */
  Usergrid.Collection.prototype.getPrevEntity = function () {
     this._iterator--;
     var hasPreviousElement = (this._iterator >= 0 && this._iterator <= this._list.length);
     if(hasPreviousElement) {
      return this.list[this._iterator];
     }
     return false;
  }

  /*
  *  Entity iteration - Resets the iterator back to the beginning
  *  of the list
  *
  *  @method resetEntityPointer
  *  @return none
  */
  Usergrid.Collection.prototype.resetEntityPointer = function () {
     this._iterator  = -1;
  }

  /*
  * Method to save off the cursor just returned by the last API call
  *
  * @public
  * @method saveCursor
  * @return none
  */
  Usergrid.Collection.prototype.saveCursor = function(cursor) {
    //if current cursor is different, grab it for next cursor
    if (this._next !== cursor) {
      this._next = cursor;
    }
  }

  /*
  * Resets the paging pointer (back to original page)
  *
  * @public
  * @method resetPaging
  * @return none
  */
  Usergrid.Collection.prototype.resetPaging = function() {
    this._previous = [];
    this._next = null;
    this._cursor = null;
  }

  /*
  *  Paging -  checks to see if there is a next page od data
  *
  *  @method hasNextPage
  *  @return {boolean} returns true if there is a next page of data, false otherwise
  */
  Usergrid.Collection.prototype.hasNextPage = function () {
    return !!this._next;
  }

  /*
  *  Paging - advances the cursor and gets the next
  *  page of data from the API.  Stores returned entities
  *  in the Entity list.
  *
  *  @method getNextPage
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  */
  Usergrid.Collection.prototype.getNextPage = function (callback) {
    if (this.hasNextPage()) {
      //set the cursor to the next page of data
      this._previous.push(this._cursor);
      this._cursor = this._next;
      //empty the list
      this._list = [];
      this.fetch(callback);
    }
  }

  /*
  *  Paging -  checks to see if there is a previous page od data
  *
  *  @method hasPreviousPage
  *  @return {boolean} returns true if there is a previous page of data, false otherwise
  */
  Usergrid.Collection.prototype.hasPreviousPage = function () {
    return (this._previous.length > 0);
  }

  /*
  *  Paging - reverts the cursor and gets the previous
  *  page of data from the API.  Stores returned entities
  *  in the Entity list.
  *
  *  @method getPreviousPage
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  */
  Usergrid.Collection.prototype.getPreviousPage = function (callback) {
    if (this.hasPreviousPage()) {
      this._next=null; //clear out next so the comparison will find the next item
      this._cursor = this._previous.pop();
      //empty the list
      this._list = [];
      this.fetch(callback);
    }
  }


  /*
   *  A class to model a Usergrid group.
   *  Set the path in the options object.
   *
   *  @constructor
   *  @param {object} options {client:client, data: {'key': 'value'}, path:'path'}
   */
  Usergrid.Group = function(options, callback) {
    this._path = options.path;
    this._list = [];
    this._client = options.client;
    this._data = options.data || {};
    this._data.type = "groups";
  }

  /*
   *  Inherit from Usergrid.Entity.
   *  Note: This only accounts for data on the group object itself.
   *  You need to use add and remove to manipulate group membership.
   */
  Usergrid.Group.prototype = new Usergrid.Entity();

  /*
  *  Fetches current group data, and members.
  *
  *  @method fetch
  *  @public
  *  @param {function} callback
  *  @returns {function} callback(err, data)
  */
  Usergrid.Group.prototype.fetch = function(callback) {
    var self = this;
    var groupEndpoint = 'groups/'+this._path;
    var memberEndpoint = 'groups/'+this._path+'/users';

    var groupOptions = {
      method:'GET',
      endpoint:groupEndpoint
    }

    var memberOptions = {
      method:'GET',
      endpoint:memberEndpoint
    }

    this._client.request(groupOptions, function(err, data){
      if(err) {
        if(self._client.logging) {
          console.log('error getting group');
        }
        if(typeof(callback) === 'function') {
          callback(err, data);
        }
      } else {
        if(data.entities) {
          var groupData = data.entities[0];
          self._data = groupData || {};
          self._client.request(memberOptions, function(err, data) {
            if(err && self._client.logging) {
              console.log('error getting group users');
            } else {
              if(data.entities) {
                var count = data.entities.length;
                self._list = [];
                for (var i = 0; i < count; i++) {
                  var uuid = data.entities[i].uuid;
                  if(uuid) {
                    var entityData = data.entities[i] || {};
                    var entityOptions = {
                      type: entityData.type,
                      client: self._client,
                      uuid:uuid,
                      data:entityData
                    };
                    var entity = new Usergrid.Entity(entityOptions);
                    self._list.push(entity);
                  }

                }
              }
            }
            if(typeof(callback) === 'function') {
              callback(err, data, self._list);
            }
          });
        }
      }
    });
  }

  /*
   *  Retrieves the members of a group.
   *
   *  @method members
   *  @public
   *  @param {function} callback
   *  @return {function} callback(err, data);
   */
  Usergrid.Group.prototype.members = function(callback) {
    if(typeof(callback) === 'function') {
      callback(null, this._list);
    }
  }

  /*
   *  Adds a user to the group, and refreshes the group object.
   *
   *  Options object: {user: user_entity}
   *
   *  @method add
   *  @public
   *  @params {object} options
   *  @param {function} callback
   *  @return {function} callback(err, data)
   */
  Usergrid.Group.prototype.add = function(options, callback) {
    var self = this;
    var options = {
      method:"POST",
      endpoint:"groups/"+this._path+"/users/"+options.user.get('username')
    }

    this._client.request(options, function(error, data){
      if(error) {
        if(typeof(callback) === 'function') {
          callback(error, data, data.entities);
        }
      } else {
        self.fetch(callback);
      }
    });
  }

  /*
   *  Removes a user from a group, and refreshes the group object.
   *
   *  Options object: {user: user_entity}
   *
   *  @method remove
   *  @public
   *  @params {object} options
   *  @param {function} callback
   *  @return {function} callback(err, data)
   */
  Usergrid.Group.prototype.remove = function(options, callback) {
    var self = this;

    var options = {
      method:"DELETE",
      endpoint:"groups/"+this._path+"/users/"+options.user.username
    }

    this._client.request(options, function(error, data){
      if(error) {
        if(typeof(callback) === 'function') {
          callback(error, data);
        }
      } else {
        self.fetch(callback);
      }
    });
  }

  /*
  * Gets feed for a group.
  *
  * @public
  * @method feed
  * @param {function} callback
  * @returns {callback} callback(err, data, activities)
  */
  Usergrid.Group.prototype.feed = function(callback) {
    var self = this;

    var endpoint = "groups/"+this._path+"/feed";

    var options = {
      method:"GET",
      endpoint:endpoint
    }

    this._client.request(options, function(err, data){
      if (err && self.logging) {
        console.log('error trying to log user in');
      }
      if(typeof(callback) === 'function') {
          callback(err, data, data.entities);
      }
    });
  }

  /*
  * Creates activity and posts to group feed.
  *
  * options object: {user: user_entity, content: "activity content"}
  *
  * @public
  * @method createGroupActivity
  * @params {object} options
  * @param {function} callback
  * @returns {callback} callback(err, entity)
  */
  Usergrid.Group.prototype.createGroupActivity = function(options, callback){
    var user = options.user;
    var options = {
      actor: {
        "displayName":user.get("username"),
        "uuid":user.get("uuid"),
        "username":user.get("username"),
        "email":user.get("email"),
        "picture":user.get("picture"),
        "image": {
          "duration":0,
          "height":80,
          "url":user.get("picture"),
          "width":80
         },
      },
      "verb":"post",
      "content":options.content };

      options.type = 'groups/'+this._path+'/activities';
      var options = {
        client:this._client,
        data:options
      }

      var entity = new Usergrid.Entity(options);
      entity.save(function(err, data) {
        if (typeof(callback) === 'function') {
          callback(err, entity);
        }
      });
  }

  /*
  * Tests if the string is a uuid
  *
  * @public
  * @method isUUID
  * @param {string} uuid The string to test
  * @returns {Boolean} true if string is uuid
  */
  function isUUID (uuid) {
    var uuidValueRegex = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
    if (!uuid) return false;
    return uuidValueRegex.test(uuid);
  }

  /*
  *  method to encode the query string parameters
  *
  *  @method encodeParams
  *  @public
  *  @params {object} params - an object of name value pairs that will be urlencoded
  *  @return {string} Returns the encoded string
  */
  function encodeParams (params) {
    tail = [];
    var item = [];
    if (params instanceof Array) {
      for (i in params) {
        item = params[i];
        if ((item instanceof Array) && (item.length > 1)) {
          tail.push(item[0] + "=" + encodeURIComponent(item[1]));
        }
      }
    } else {
      for (var key in params) {
        if (params.hasOwnProperty(key)) {
          var value = params[key];
          if (value instanceof Array) {
            for (i in value) {
              item = value[i];
              tail.push(key + "=" + encodeURIComponent(item));
            }
          } else {
            tail.push(key + "=" + encodeURIComponent(value));
          }
        }
      }
    }
    return tail.join("&");
  }
/*
 *  A class to model a Usergrid event.
 *
 *  @constructor
 *  @param {object} options {timestamp:0, category:'value', counters:{name : value}}
 *  @returns {callback} callback(err, event)
 */
Usergrid.Counter = function(options, callback) {
  var self=this;
  this._client = options.client;
  this._data = options.data || {};
  this._data.category = options.category||"UNKNOWN";
  this._data.timestamp = options.timestamp||0;
  this._data.type = "events";
  this._data.counters=options.counters||{};
  if(typeof(callback) === 'function') {
    callback.call(self, false, self);
  }
  //this.save(callback);
};
var COUNTER_RESOLUTIONS=[
  'all', 'minute', 'five_minutes', 'half_hour',
  'hour', 'six_day', 'day', 'week', 'month'
];
/*
 *  Inherit from Usergrid.Entity.
 *  Note: This only accounts for data on the group object itself.
 *  You need to use add and remove to manipulate group membership.
 */
Usergrid.Counter.prototype = new Usergrid.Entity();

/*
 * overrides Entity.prototype.fetch. Returns all data for counters
 * associated with the object as specified in the constructor
 *
 * @public
 * @method increment
 * @param {function} callback
 * @returns {callback} callback(err, event)
 */
Usergrid.Counter.prototype.fetch=function(callback){
  this.getData({}, callback);
}
/*
 * increments the counter for a specific event
 *
 * options object: {name: counter_name}
 *
 * @public
 * @method increment
 * @params {object} options
 * @param {function} callback
 * @returns {callback} callback(err, event)
 */
Usergrid.Counter.prototype.increment=function(options, callback){
  var self=this,
    name=options.name,
    value=options.value;
  if(!name){
    if(typeof(callback) === 'function') {
      return callback.call(self, true, "'value' for increment, decrement must be a number");
    }
  }else if(isNaN(value)){
    if(typeof(callback) === 'function') {
      return callback.call(self, true, "'value' for increment, decrement must be a number");
    }
  }else{
    self._data.counters[name]=(parseInt(value))||1;
    return self.save(callback);
  }
};
/*
 * decrements the counter for a specific event
 *
 * options object: {name: counter_name}
 *
 * @public
 * @method decrement
 * @params {object} options
 * @param {function} callback
 * @returns {callback} callback(err, event)
 */

Usergrid.Counter.prototype.decrement=function(options, callback){
  var self=this,
    name=options.name,
    value=options.value;
  self.increment({name:name, value:-((parseInt(value))||1)}, callback);
};
/*
 * resets the counter for a specific event
 *
 * options object: {name: counter_name}
 *
 * @public
 * @method reset
 * @params {object} options
 * @param {function} callback
 * @returns {callback} callback(err, event)
 */

Usergrid.Counter.prototype.reset=function(options, callback){
  var self=this,
    name=options.name;
  self.increment({name:name, value:0}, callback);
};

/*
 * gets data for one or more counters over a given
 * time period at a specified resolution
 *
 * options object: {
 *                   counters: ['counter1', 'counter2', ...],
 *                   start: epoch timestamp or ISO date string,
 *                   end: epoch timestamp or ISO date string,
 *                   resolution: one of ('all', 'minute', 'five_minutes', 'half_hour', 'hour', 'six_day', 'day', 'week', or 'month')
 *                   }
 *
 * @public
 * @method getData
 * @params {object} options
 * @param {function} callback
 * @returns {callback} callback(err, event)
 */
Usergrid.Counter.prototype.getData=function(options, callback){
  var start_time,
      end_time,
      start=options.start||0,
      end=options.end||Date.now(),
      resolution=(options.resolution||'all').toLowerCase(),
      counters=options.counters||Object.keys(this._data.counters),
      res=(resolution||'all').toLowerCase();
  if(COUNTER_RESOLUTIONS.indexOf(res)===-1){
    res='all';
  }
  if(start){
    switch(typeof start){
      case "undefined":
        start_time=0;
        break;
      case "number":
        start_time=start;
        break;
      case "string":
        start_time=(isNaN(start))?Date.parse(start):parseInt(start);
        break;
      default:
        start_time=Date.parse(start.toString());
    }
  }
  if(end){
    switch(typeof end){
      case "undefined":
        end_time=Date.now();
        break;
      case "number":
        end_time=end;
        break;
      case "string":
        end_time=(isNaN(end))?Date.parse(end):parseInt(end);
        break;
      default:
        end_time=Date.parse(end.toString());
    }
  }
  var self=this;
  //https://api.usergrid.com/yourorgname/sandbox/counters?counter=test_counter
  var params=Object.keys(counters).map(function(counter){
      return ["counter", encodeURIComponent(counters[counter])].join('=');
    });
  params.push('resolution='+res)
  params.push('start_time='+String(start_time))
  params.push('end_time='+String(end_time))

  var endpoint="counters?"+params.join('&');
  this._client.request({endpoint:endpoint}, function(err, data){
    if(data.counters && data.counters.length){
      data.counters.forEach(function(counter){
        self._data.counters[counter.name]=counter.value||counter.values;
      })
    }
    if(typeof(callback) === 'function') {
      callback.call(self, err, data);
    }
  })
};

exports.client = Usergrid.Client;
exports.entity = Usergrid.Entity;
exports.collection = Usergrid.Collection;
exports.group = Usergrid.Group;
exports.counter = Usergrid.Counter;
exports.AUTH_CLIENT_ID = AUTH_CLIENT_ID;
exports.AUTH_APP_USER = AUTH_APP_USER;
exports.AUTH_NONE = AUTH_NONE;
