//
// 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 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:'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;
