text: 'use strict';
  
  /* jshint ignore:start */
  /**
   * This code was generated by
   * \ / _    _  _|   _  _
   *  | (_)\/(_)(_|\/| |(/_  v1.0.0
   *       /       /
   */
  /* jshint ignore:end */
  
  var Q = require('q');  /* jshint ignore:line */
  var _ = require('lodash');  /* jshint ignore:line */
  var util = require('util');  /* jshint ignore:line */
  var Page = require('../../../../base/Page');  /* jshint ignore:line */
  var deserialize = require(
      '../../../../base/deserialize');  /* jshint ignore:line */
  var values = require('../../../../base/values');  /* jshint ignore:line */
  
  var CertificateList;
  var CertificatePage;
  var CertificateInstance;
  var CertificateContext;
  
  /* jshint ignore:start */
  /**
   * @description Initialize the CertificateList
   * PLEASE NOTE that this class contains preview products that are subject to change. Use them with caution. If you currently do not have developer preview access, please contact help@twilio.com.
   *
   * @param {Twilio.Preview.DeployedDevices} version - Version of the resource
   * @param {string} fleetSid - The unique identifier of the Fleet.
   */
  /* jshint ignore:end */
  CertificateList = function CertificateList(version, fleetSid) {
    /* jshint ignore:start */
    /**
     * @param {string} sid - sid of instance
     *
     * @returns {Twilio.Preview.DeployedDevices.FleetContext.CertificateContext}
     */
    /* jshint ignore:end */
    function CertificateListInstance(sid) {
      return CertificateListInstance.get(sid);
    }
  
    CertificateListInstance._version = version;
    // Path Solution
    CertificateListInstance._solution = {fleetSid: fleetSid};
    CertificateListInstance._uri = _.template(
      '/Fleets/<%= fleetSid %>/Certificates' // jshint ignore:line
    )(CertificateListInstance._solution);
    /* jshint ignore:start */
    /**
     * create a CertificateInstance
     *
     * @param {object} opts - Options for request
     * @param {string} opts.certificateData - The public certificate data.
     * @param {string} [opts.friendlyName] -
     *          The human readable description for this Certificate.
     * @param {string} [opts.deviceSid] -
     *          The unique identifier of a Device to be authenticated.
     * @param {function} [callback] - Callback to handle processed record
     *
     * @returns {Promise} Resolves to processed CertificateInstance
     */
    /* jshint ignore:end */
    CertificateListInstance.create = function create(opts, callback) {
      if (_.isUndefined(opts)) {
        throw new Error('Required parameter "opts" missing.');
      }
      if (_.isUndefined(opts.certificateData)) {
        throw new Error('Required parameter "opts.certificateData" missing.');
      }
  
      var deferred = Q.defer();
      var data = values.of({
        'CertificateData': _.get(opts, 'certificateData'),
        'FriendlyName': _.get(opts, 'friendlyName'),
        'DeviceSid': _.get(opts, 'deviceSid')
      });
  
      var promise = this._version.create({uri: this._uri, method: 'POST', data: data});
  
      promise = promise.then(function(payload) {
        deferred.resolve(new CertificateInstance(
          this._version,
          payload,
          this._solution.fleetSid,
          this._solution.sid
        ));
      }.bind(this));
  
      promise.catch(function(error) {
        deferred.reject(error);
      });
  
      if (_.isFunction(callback)) {
        deferred.promise.nodeify(callback);
      }
  
      return deferred.promise;
    };
  
    /* jshint ignore:start */
    /**
     * Streams CertificateInstance records from the API.
     *
     * This operation lazily loads records as efficiently as possible until the limit
     * is reached.
     *
     * The results are passed into the callback function, so this operation is memory efficient.
     *
     * If a function is passed as the first argument, it will be used as the callback function.
     *
     * @param {object} [opts] - Options for request
     * @param {string} [opts.deviceSid] -
     *          Find all Certificates authenticating specified Device.
     * @param {number} [opts.limit] -
     *         Upper limit for the number of records to return.
     *         each() guarantees never to return more than limit.
     *         Default is no limit
     * @param {number} [opts.pageSize] -
     *         Number of records to fetch per request,
     *         when not set will use the default value of 50 records.
     *         If no pageSize is defined but a limit is defined,
     *         each() will attempt to read the limit with the most efficient
     *         page size, i.e. min(limit, 1000)
     * @param {Function} [opts.callback] -
     *         Function to process each record. If this and a positional
     *         callback are passed, this one will be used
     * @param {Function} [opts.done] -
     *          Function to be called upon completion of streaming
     * @param {Function} [callback] - Function to process each record
     */
    /* jshint ignore:end */
    CertificateListInstance.each = function each(opts, callback) {
      if (_.isFunction(opts)) {
        callback = opts;
        opts = {};
      }
      opts = opts || {};
      if (opts.callback) {
        callback = opts.callback;
      }
      if (_.isUndefined(callback)) {
        throw new Error('Callback function must be provided');
      }
  
      var done = false;
      var currentPage = 1;
      var currentResource = 0;
      var limits = this._version.readLimits({
        limit: opts.limit,
        pageSize: opts.pageSize
      });
  
      function onComplete(error) {
        done = true;
        if (_.isFunction(opts.done)) {
          opts.done(error);
        }
      }
  
      function fetchNextPage(fn) {
        var promise = fn();
        if (_.isUndefined(promise)) {
          onComplete();
          return;
        }
  
        promise.then(function(page) {
          _.each(page.instances, function(instance) {
            if (done || (!_.isUndefined(opts.limit) && currentResource >= opts.limit)) {
              done = true;
              return false;
            }
  
            currentResource++;
            callback(instance, onComplete);
          });
  
          if ((limits.pageLimit && limits.pageLimit <= currentPage)) {
            onComplete();
          } else if (!done) {
            currentPage++;
            fetchNextPage(_.bind(page.nextPage, page));
          }
        });
  
        promise.catch(onComplete);
      }
  
      fetchNextPage(_.bind(this.page, this, _.merge(opts, limits)));
    };
  
    /* jshint ignore:start */
    /**
     * Lists CertificateInstance records from the API as a list.
     *
     * If a function is passed as the first argument, it will be used as the callback function.
     *
     * @param {object} [opts] - Options for request
     * @param {string} [opts.deviceSid] -
     *          Find all Certificates authenticating specified Device.
     * @param {number} [opts.limit] -
     *         Upper limit for the number of records to return.
     *         list() guarantees never to return more than limit.
     *         Default is no limit
     * @param {number} [opts.pageSize] -
     *         Number of records to fetch per request,
     *         when not set will use the default value of 50 records.
     *         If no page_size is defined but a limit is defined,
     *         list() will attempt to read the limit with the most
     *         efficient page size, i.e. min(limit, 1000)
     * @param {function} [callback] - Callback to handle list of records
     *
     * @returns {Promise} Resolves to a list of records
     */
    /* jshint ignore:end */
    CertificateListInstance.list = function list(opts, callback) {
      if (_.isFunction(opts)) {
        callback = opts;
        opts = {};
      }
      opts = opts || {};
      var deferred = Q.defer();
      var allResources = [];
      opts.callback = function(resource, done) {
        allResources.push(resource);
  
        if (!_.isUndefined(opts.limit) && allResources.length === opts.limit) {
          done();
        }
      };
  
      opts.done = function(error) {
        if (_.isUndefined(error)) {
          deferred.resolve(allResources);
        } else {
          deferred.reject(error);
        }
      };
  
      if (_.isFunction(callback)) {
        deferred.promise.nodeify(callback);
      }
  
      this.each(opts);
      return deferred.promise;
    };
  
    /* jshint ignore:start */
    /**
     * Retrieve a single page of CertificateInstance records from the API.
     * Request is executed immediately
     *
     * If a function is passed as the first argument, it will be used as the callback function.
     *
     * @param {object} [opts] - Options for request
     * @param {string} [opts.deviceSid] -
     *          Find all Certificates authenticating specified Device.
     * @param {string} [opts.pageToken] - PageToken provided by the API
     * @param {number} [opts.pageNumber] -
     *          Page Number, this value is simply for client state
     * @param {number} [opts.pageSize] - Number of records to return, defaults to 50
     * @param {function} [callback] - Callback to handle list of records
     *
     * @returns {Promise} Resolves to a list of records
     */
    /* jshint ignore:end */
    CertificateListInstance.page = function page(opts, callback) {
      if (_.isFunction(opts)) {
        callback = opts;
        opts = {};
      }
      opts = opts || {};
  
      var deferred = Q.defer();
      var data = values.of({
        'DeviceSid': _.get(opts, 'deviceSid'),
        'PageToken': opts.pageToken,
        'Page': opts.pageNumber,
        'PageSize': opts.pageSize
      });
  
      var promise = this._version.page({uri: this._uri, method: 'GET', params: data});
  
      promise = promise.then(function(payload) {
        deferred.resolve(new CertificatePage(this._version, payload, this._solution));
      }.bind(this));
  
      promise.catch(function(error) {
        deferred.reject(error);
      });
  
      if (_.isFunction(callback)) {
        deferred.promise.nodeify(callback);
      }
  
      return deferred.promise;
    };
  
    /* jshint ignore:start */
    /**
     * Retrieve a single target page of CertificateInstance records from the API.
     * Request is executed immediately
     *
     * If a function is passed as the first argument, it will be used as the callback function.
     *
     * @param {string} [targetUrl] - API-generated URL for the requested results page
     * @param {function} [callback] - Callback to handle list of records
     *
     * @returns {Promise} Resolves to a list of records
     */
    /* jshint ignore:end */
    CertificateListInstance.getPage = function getPage(targetUrl, callback) {
      var deferred = Q.defer();
  
      var promise = this._version._domain.twilio.request({method: 'GET', uri: targetUrl});
  
      promise = promise.then(function(payload) {
        deferred.resolve(new CertificatePage(this._version, payload, this._solution));
      }.bind(this));
  
      promise.catch(function(error) {
        deferred.reject(error);
      });
  
      if (_.isFunction(callback)) {
        deferred.promise.nodeify(callback);
      }
  
      return deferred.promise;
    };
  
    /* jshint ignore:start */
    /**
     * Constructs a certificate
     *
     * @param {string} sid - A string that uniquely identifies the Certificate.
     *
     * @returns {Twilio.Preview.DeployedDevices.FleetContext.CertificateContext}
     */
    /* jshint ignore:end */
    CertificateListInstance.get = function get(sid) {
      return new CertificateContext(this._version, this._solution.fleetSid, sid);
    };
  
    /* jshint ignore:start */
    /**
     * Provide a user-friendly representation
     *
     * @returns Object
     */
    /* jshint ignore:end */
    CertificateListInstance.toJSON = function toJSON() {
      return this._solution;
    };
  
    CertificateListInstance[util.inspect.custom] = function inspect(depth, options)
        {
      return util.inspect(this.toJSON(), options);
    };
  
    return CertificateListInstance;
  };
  
  
  /* jshint ignore:start */
  /**
   * Initialize the CertificatePagePLEASE NOTE that this class contains preview products that are subject to change. Use them with caution. If you currently do not have developer preview access, please contact help@twilio.com.
   *
   * @param {DeployedDevices} version - Version of the resource
   * @param {Response<string>} response - Response from the API
   * @param {CertificateSolution} solution - Path solution
   *
   * @returns CertificatePage
   */
  /* jshint ignore:end */
  CertificatePage = function CertificatePage(version, response, solution) {
    // Path Solution
    this._solution = solution;
  
    Page.prototype.constructor.call(this, version, response, this._solution);
  };
  
  _.extend(CertificatePage.prototype, Page.prototype);
  CertificatePage.prototype.constructor = CertificatePage;
  
  /* jshint ignore:start */
  /**
   * Build an instance of CertificateInstance
   *
   * @param {CertificatePayload} payload - Payload response from the API
   *
   * @returns CertificateInstance
   */
  /* jshint ignore:end */
  CertificatePage.prototype.getInstance = function getInstance(payload) {
    return new CertificateInstance(this._version, payload, this._solution.fleetSid);
  };
  
  /* jshint ignore:start */
  /**
   * Provide a user-friendly representation
   *
   * @returns Object
   */
  /* jshint ignore:end */
  CertificatePage.prototype.toJSON = function toJSON() {
    let clone = {};
    _.forOwn(this, function(value, key) {
      if (!_.startsWith(key, '_') && ! _.isFunction(value)) {
        clone[key] = value;
      }
    });
    return clone;
  };
  
  CertificatePage.prototype[util.inspect.custom] = function inspect(depth,
      options) {
    return util.inspect(this.toJSON(), options);
  };
  
  
  /* jshint ignore:start */
  /**
   * Initialize the CertificateContextPLEASE NOTE that this class contains preview products that are subject to change. Use them with caution. If you currently do not have developer preview access, please contact help@twilio.com.
   *
   * @property {string} sid - A string that uniquely identifies this Certificate.
   * @property {string} url - URL of this Certificate.
   * @property {string} friendlyName -
   *          A human readable description for this Certificate.
   * @property {string} fleetSid - The unique identifier of the Fleet.
   * @property {string} accountSid - The unique SID that identifies this Account.
   * @property {string} deviceSid - The unique identifier of a mapped Device.
   * @property {string} thumbprint - A Certificate unique payload hash.
   * @property {Date} dateCreated - The date this Certificate was created.
   * @property {Date} dateUpdated - The date this Certificate was updated.
   *
   * @param {DeployedDevices} version - Version of the resource
   * @param {CertificatePayload} payload - The instance payload
   * @param {sid_like} fleetSid - The unique identifier of the Fleet.
   * @param {sid} sid - A string that uniquely identifies the Certificate.
   */
  /* jshint ignore:end */
  CertificateInstance = function CertificateInstance(version, payload, fleetSid,
                                                      sid) {
    this._version = version;
  
    // Marshaled Properties
    this.sid = payload.sid; // jshint ignore:line
    this.url = payload.url; // jshint ignore:line
    this.friendlyName = payload.friendly_name; // jshint ignore:line
    this.fleetSid = payload.fleet_sid; // jshint ignore:line
    this.accountSid = payload.account_sid; // jshint ignore:line
    this.deviceSid = payload.device_sid; // jshint ignore:line
    this.thumbprint = payload.thumbprint; // jshint ignore:line
    this.dateCreated = deserialize.iso8601DateTime(payload.date_created); // jshint ignore:line
    this.dateUpdated = deserialize.iso8601DateTime(payload.date_updated); // jshint ignore:line
  
    // Context
    this._context = undefined;
    this._solution = {fleetSid: fleetSid, sid: sid || this.sid, };
  };
  
  Object.defineProperty(CertificateInstance.prototype,
    '_proxy', {
    get: function() {
      if (!this._context) {
        this._context = new CertificateContext(this._version, this._solution.fleetSid, this._solution.sid);
      }
  
      return this._context;
    }
  });
  
  /* jshint ignore:start */
  /**
   * fetch a CertificateInstance
   *
   * @param {function} [callback] - Callback to handle processed record
   *
   * @returns {Promise} Resolves to processed CertificateInstance
   */
  /* jshint ignore:end */
  CertificateInstance.prototype.fetch = function fetch(callback) {
    return this._proxy.fetch(callback);
  };
  
  /* jshint ignore:start */
  /**
   * remove a CertificateInstance
   *
   * @param {function} [callback] - Callback to handle processed record
   *
   * @returns {Promise} Resolves to processed CertificateInstance
   */
  /* jshint ignore:end */
  CertificateInstance.prototype.remove = function remove(callback) {
    return this._proxy.remove(callback);
  };
  
  /* jshint ignore:start */
  /**
   * update a CertificateInstance
   *
   * @param {object} [opts] - Options for request
   * @param {string} [opts.friendlyName] -
   *          The human readable description for this Certificate.
   * @param {string} [opts.deviceSid] -
   *          The unique identifier of a Device to be authenticated.
   * @param {function} [callback] - Callback to handle processed record
   *
   * @returns {Promise} Resolves to processed CertificateInstance
   */
  /* jshint ignore:end */
  CertificateInstance.prototype.update = function update(opts, callback) {
    return this._proxy.update(opts, callback);
  };
  
  /* jshint ignore:start */
  /**
   * Provide a user-friendly representation
   *
   * @returns Object
   */
  /* jshint ignore:end */
  CertificateInstance.prototype.toJSON = function toJSON() {
    let clone = {};
    _.forOwn(this, function(value, key) {
      if (!_.startsWith(key, '_') && ! _.isFunction(value)) {
        clone[key] = value;
      }
    });
    return clone;
  };
  
  CertificateInstance.prototype[util.inspect.custom] = function inspect(depth,
      options) {
    return util.inspect(this.toJSON(), options);
  };
  
  
  /* jshint ignore:start */
  /**
   * Initialize the CertificateContextPLEASE NOTE that this class contains preview products that are subject to change. Use them with caution. If you currently do not have developer preview access, please contact help@twilio.com.
   *
   * @param {DeployedDevices} version - Version of the resource
   * @param {sid_like} fleetSid - The fleet_sid
   * @param {sid} sid - A string that uniquely identifies the Certificate.
   */
  /* jshint ignore:end */
  CertificateContext = function CertificateContext(version, fleetSid, sid) {
    this._version = version;
  
    // Path Solution
    this._solution = {fleetSid: fleetSid, sid: sid, };
    this._uri = _.template(
      '/Fleets/<%= fleetSid %>/Certificates/<%= sid %>' // jshint ignore:line
    )(this._solution);
  };
  
  /* jshint ignore:start */
  /**
   * fetch a CertificateInstance
   *
   * @param {function} [callback] - Callback to handle processed record
   *
   * @returns {Promise} Resolves to processed CertificateInstance
   */
  /* jshint ignore:end */
  CertificateContext.prototype.fetch = function fetch(callback) {
    var deferred = Q.defer();
    var promise = this._version.fetch({uri: this._uri, method: 'GET'});
  
    promise = promise.then(function(payload) {
      deferred.resolve(new CertificateInstance(
        this._version,
        payload,
        this._solution.fleetSid,
        this._solution.sid
      ));
    }.bind(this));
  
    promise.catch(function(error) {
      deferred.reject(error);
    });
  
    if (_.isFunction(callback)) {
      deferred.promise.nodeify(callback);
    }
  
    return deferred.promise;
  };
  
  /* jshint ignore:start */
  /**
   * remove a CertificateInstance
   *
   * @param {function} [callback] - Callback to handle processed record
   *
   * @returns {Promise} Resolves to processed CertificateInstance
   */
  /* jshint ignore:end */
  CertificateContext.prototype.remove = function remove(callback) {
    var deferred = Q.defer();
    var promise = this._version.remove({uri: this._uri, method: 'DELETE'});
  
    promise = promise.then(function(payload) {
      deferred.resolve(payload);
    }.bind(this));
  
    promise.catch(function(error) {
      deferred.reject(error);
    });
  
    if (_.isFunction(callback)) {
      deferred.promise.nodeify(callback);
    }
  
    return deferred.promise;
  };
  
  /* jshint ignore:start */
  /**
   * update a CertificateInstance
   *
   * @param {object} [opts] - Options for request
   * @param {string} [opts.friendlyName] -
   *          The human readable description for this Certificate.
   * @param {string} [opts.deviceSid] -
   *          The unique identifier of a Device to be authenticated.
   * @param {function} [callback] - Callback to handle processed record
   *
   * @returns {Promise} Resolves to processed CertificateInstance
   */
  /* jshint ignore:end */
  CertificateContext.prototype.update = function update(opts, callback) {
    if (_.isFunction(opts)) {
      callback = opts;
      opts = {};
    }
    opts = opts || {};
  
    var deferred = Q.defer();
    var data = values.of({
      'FriendlyName': _.get(opts, 'friendlyName'),
      'DeviceSid': _.get(opts, 'deviceSid')
    });
  
    var promise = this._version.update({uri: this._uri, method: 'POST', data: data});
  
    promise = promise.then(function(payload) {
      deferred.resolve(new CertificateInstance(
        this._version,
        payload,
        this._solution.fleetSid,
        this._solution.sid
      ));
    }.bind(this));
  
    promise.catch(function(error) {
      deferred.reject(error);
    });
  
    if (_.isFunction(callback)) {
      deferred.promise.nodeify(callback);
    }
  
    return deferred.promise;
  };
  
  /* jshint ignore:start */
  /**
   * Provide a user-friendly representation
   *
   * @returns Object
   */
  /* jshint ignore:end */
  CertificateContext.prototype.toJSON = function toJSON() {
    return this._solution;
  };
  
  CertificateContext.prototype[util.inspect.custom] = function inspect(depth,
      options) {
    return util.inspect(this.toJSON(), options);
  };
  
  module.exports = {
    CertificateList: CertificateList,
    CertificatePage: CertificatePage,
    CertificateInstance: CertificateInstance,
    CertificateContext: CertificateContext
  };
  