text: var AWS = require('./core');
  require('./credentials');
  require('./credentials/credential_provider_chain');
  
  /**
   * The main configuration class used by all service objects to set
   * the region, credentials, and other options for requests.
   *
   * By default, credentials and region settings are left unconfigured.
   * This should be configured by the application before using any
   * AWS service APIs.
   *
   * In order to set global configuration options, properties should
   * be assigned to the global {AWS.config} object.
   *
   * @see AWS.config
   *
   * @!group General Configuration Options
   *
   * @!attribute credentials
   *   @return [AWS.Credentials] the AWS credentials to sign requests with.
   *
   * @!attribute region
   *   @example Set the global region setting to us-west-2
   *     AWS.config.update({region: 'us-west-2'});
   *   @return [AWS.Credentials] The region to send service requests to.
   *   @see http://docs.amazonwebservices.com/general/latest/gr/rande.html
   *     A list of available endpoints for each AWS service
   *
   * @!attribute maxRetries
   *   @return [Integer] the maximum amount of retries to perform for a
   *     service request. By default this value is calculated by the specific
   *     service object that the request is being made to.
   *
   * @!attribute maxRedirects
   *   @return [Integer] the maximum amount of redirects to follow for a
   *     service request. Defaults to 10.
   *
   * @!attribute paramValidation
   *   @return [Boolean] whether input parameters should be validated against
   *     the operation description before sending the request. Defaults to true.
   *
   * @!attribute computeChecksums
   *   @return [Boolean] whether to compute checksums for payload bodies when
   *     the service accepts it (currently supported in S3 only).
   *
   * @!attribute convertResponseTypes
   *   @return [Boolean] whether types are converted when parsing response data.
   *     Currently only supported for JSON based services. Turning this off may
   *     improve performance on large response payloads. Defaults to `true`.
   *
   * @!attribute correctClockSkew
   *   @return [Boolean] whether to apply a clock skew correction and retry
   *     requests that fail because of an skewed client clock. Defaults to
   *     `false`.
   *
   * @!attribute sslEnabled
   *   @return [Boolean] whether SSL is enabled for requests
   *
   * @!attribute s3ForcePathStyle
   *   @return [Boolean] whether to force path style URLs for S3 objects
   *
   * @!attribute s3BucketEndpoint
   *   @note Setting this configuration option requires an `endpoint` to be
   *     provided explicitly to the service constructor.
   *   @return [Boolean] whether the provided endpoint addresses an individual
   *     bucket (false if it addresses the root API endpoint).
   *
   * @!attribute httpOptions
   *   @return [map] A set of options to pass to the low-level HTTP request.
   *     Currently supported options are:
   *
   *     * **proxy** [String] &mdash; the URL to proxy requests through
   *     * **agent** [http.Agent, https.Agent] &mdash; the Agent object to perform
   *       HTTP requests with. Used for connection pooling. Defaults to the global
   *       agent (`http.globalAgent`) for non-SSL connections. Note that for
   *       SSL connections, a special Agent object is used in order to enable
   *       peer certificate verification. This feature is only supported in the
   *       Node.js environment.
   *     * **timeout** [Integer] &mdash; The number of milliseconds to wait before
   *       giving up on a connection attempt. Defaults to two minutes (120000).
   *     * **xhrAsync** [Boolean] &mdash; Whether the SDK will send asynchronous
   *       HTTP requests. Used in the browser environment only. Set to false to
   *       send requests synchronously. Defaults to true (async on).
   *     * **xhrWithCredentials** [Boolean] &mdash; Sets the "withCredentials"
   *       property of an XMLHttpRequest object. Used in the browser environment
   *       only. Defaults to false.
   * @!attribute logger
   *   @return [#write,#log] an object that responds to .write() (like a stream)
   *     or .log() (like the console object) in order to log information about
   *     requests
   *
   * @!attribute systemClockOffset
   *   @return [Number] an offset value in milliseconds to apply to all signing
   *     times. Use this to compensate for clock skew when your system may be
   *     out of sync with the service time. Note that this configuration option
   *     can only be applied to the global `AWS.config` object and cannot be
   *     overridden in service-specific configuration. Defaults to 0 milliseconds.
   *
   * @!attribute signatureVersion
   *   @return [String] the signature version to sign requests with (overriding
   *     the API configuration). Possible values are: 'v2', 'v3', 'v4'.
   *
   * @!attribute signatureCache
   *   @return [Boolean] whether the signature to sign requests with (overriding
   *     the API configuration) is cached. Only applies to the signature version 'v4'.
   *     Defaults to `true`.
   */
  AWS.Config = AWS.util.inherit({
    /**
     * @!endgroup
     */
  
    /**
     * Creates a new configuration object. This is the object that passes
     * option data along to service requests, including credentials, security,
     * region information, and some service specific settings.
     *
     * @example Creating a new configuration object with credentials and region
     *   var config = new AWS.Config({
     *     accessKeyId: 'AKID', secretAccessKey: 'SECRET', region: 'us-west-2'
     *   });
     * @option options accessKeyId [String] your AWS access key ID.
     * @option options secretAccessKey [String] your AWS secret access key.
     * @option options sessionToken [AWS.Credentials] the optional AWS
     *   session token to sign requests with.
     * @option options credentials [AWS.Credentials] the AWS credentials
     *   to sign requests with. You can either specify this object, or
     *   specify the accessKeyId and secretAccessKey options directly.
     * @option options credentialProvider [AWS.CredentialProviderChain] the
     *   provider chain used to resolve credentials if no static `credentials`
     *   property is set.
     * @option options region [String] the region to send service requests to.
     *   See {region} for more information.
     * @option options maxRetries [Integer] the maximum amount of retries to
     *   attempt with a request. See {maxRetries} for more information.
     * @option options maxRedirects [Integer] the maximum amount of redirects to
     *   follow with a request. See {maxRedirects} for more information.
     * @option options sslEnabled [Boolean] whether to enable SSL for
     *   requests.
     * @option options paramValidation [Boolean] whether parameter validation
     *   is on.
     * @option options computeChecksums [Boolean] whether to compute checksums
     *   for payload bodies when the service accepts it (currently supported
     *   in S3 only)
     * @option options convertResponseTypes [Boolean] whether types are converted
     *     when parsing response data. Currently only supported for JSON based
     *     services. Turning this off may improve performance on large response
     *     payloads. Defaults to `true`.
     * @option options correctClockSkew [Boolean] whether to apply a clock skew
     *     correction and retry requests that fail because of an skewed client
     *     clock. Defaults to `false`.
     * @option options s3ForcePathStyle [Boolean] whether to force path
     *   style URLs for S3 objects.
     * @option options s3BucketEndpoint [Boolean] whether the provided endpoint
     *   addresses an individual bucket (false if it addresses the root API
     *   endpoint). Note that setting this configuration option requires an
     *   `endpoint` to be provided explicitly to the service constructor.
     * @option options httpOptions [map] A set of options to pass to the low-level
     *   HTTP request. Currently supported options are:
     *
     *   * **proxy** [String] &mdash; the URL to proxy requests through
     *   * **agent** [http.Agent, https.Agent] &mdash; the Agent object to perform
     *     HTTP requests with. Used for connection pooling. Defaults to the global
     *     agent (`http.globalAgent`) for non-SSL connections. Note that for
     *     SSL connections, a special Agent object is used in order to enable
     *     peer certificate verification. This feature is only available in the
     *     Node.js environment.
     *   * **timeout** [Integer] &mdash; Sets the socket to timeout after timeout
     *     milliseconds of inactivity on the socket. Defaults to two minutes
     *     (120000).
     *   * **xhrAsync** [Boolean] &mdash; Whether the SDK will send asynchronous
     *     HTTP requests. Used in the browser environment only. Set to false to
     *     send requests synchronously. Defaults to true (async on).
     *   * **xhrWithCredentials** [Boolean] &mdash; Sets the "withCredentials"
     *     property of an XMLHttpRequest object. Used in the browser environment
     *     only. Defaults to false.
     * @option options apiVersion [String, Date] a String in YYYY-MM-DD format
     *   (or a date) that represents the latest possible API version that can be
     *   used in all services (unless overridden by `apiVersions`). Specify
     *   'latest' to use the latest possible version.
     * @option options apiVersions [map<String, String|Date>] a map of service
     *   identifiers (the lowercase service class name) with the API version to
     *   use when instantiating a service. Specify 'latest' for each individual
     *   that can use the latest available version.
     * @option options logger [#write,#log] an object that responds to .write()
     *   (like a stream) or .log() (like the console object) in order to log
     *   information about requests
     * @option options systemClockOffset [Number] an offset value in milliseconds
     *   to apply to all signing times. Use this to compensate for clock skew
     *   when your system may be out of sync with the service time. Note that
     *   this configuration option can only be applied to the global `AWS.config`
     *   object and cannot be overridden in service-specific configuration.
     *   Defaults to 0 milliseconds.
     * @option options signatureVersion [String] the signature version to sign
     *   requests with (overriding the API configuration). Possible values are:
     *   'v2', 'v3', 'v4'.
     * @option options signatureCache [Boolean] whether the signature to sign
     *   requests with (overriding the API configuration) is cached. Only applies
     *   to the signature version 'v4'. Defaults to `true`.
     */
    constructor: function Config(options) {
      if (options === undefined) options = {};
      options = this.extractCredentials(options);
  
      AWS.util.each.call(this, this.keys, function (key, value) {
        this.set(key, options[key], value);
      });
    },
  
    /**
     * @!group Managing Credentials
     */
  
    /**
     * Loads credentials from the configuration object. This is used internally
     * by the SDK to ensure that refreshable {Credentials} objects are properly
     * refreshed and loaded when sending a request. If you want to ensure that
     * your credentials are loaded prior to a request, you can use this method
     * directly to provide accurate credential data stored in the object.
     *
     * @note If you configure the SDK with static or environment credentials,
     *   the credential data should already be present in {credentials} attribute.
     *   This method is primarily necessary to load credentials from asynchronous
     *   sources, or sources that can refresh credentials periodically.
     * @example Getting your access key
     *   AWS.config.getCredentials(function(err) {
     *     if (err) console.log(err.stack); // credentials not loaded
     *     else console.log("Access Key:", AWS.config.credentials.accessKeyId);
     *   })
     * @callback callback function(err)
     *   Called when the {credentials} have been properly set on the configuration
     *   object.
     *
     *   @param err [Error] if this is set, credentials were not successfuly
     *     loaded and this error provides information why.
     * @see credentials
     * @see Credentials
     */
    getCredentials: function getCredentials(callback) {
      var self = this;
  
      function finish(err) {
        callback(err, err ? null : self.credentials);
      }
  
      function credError(msg, err) {
        return new AWS.util.error(err || new Error(), {
          code: 'CredentialsError', message: msg
        });
      }
  
      function getAsyncCredentials() {
        self.credentials.get(function(err) {
          if (err) {
            var msg = 'Could not load credentials from ' +
              self.credentials.constructor.name;
            err = credError(msg, err);
          }
          finish(err);
        });
      }
  
      function getStaticCredentials() {
        var err = null;
        if (!self.credentials.accessKeyId || !self.credentials.secretAccessKey) {
          err = credError('Missing credentials');
        }
        finish(err);
      }
  
      if (self.credentials) {
        if (typeof self.credentials.get === 'function') {
          getAsyncCredentials();
        } else { // static credentials
          getStaticCredentials();
        }
      } else if (self.credentialProvider) {
        self.credentialProvider.resolve(function(err, creds) {
          if (err) {
            err = credError('Could not load credentials from any providers', err);
          }
          self.credentials = creds;
          finish(err);
        });
      } else {
        finish(credError('No credentials to load'));
      }
    },
  
    /**
     * @!group Loading and Setting Configuration Options
     */
  
    /**
     * @overload update(options, allowUnknownKeys = false)
     *   Updates the current configuration object with new options.
     *
     *   @example Update maxRetries property of a configuration object
     *     config.update({maxRetries: 10});
     *   @param [Object] options a map of option keys and values.
     *   @param [Boolean] allowUnknownKeys whether unknown keys can be set on
     *     the configuration object. Defaults to `false`.
     *   @see constructor
     */
    update: function update(options, allowUnknownKeys) {
      allowUnknownKeys = allowUnknownKeys || false;
      options = this.extractCredentials(options);
      AWS.util.each.call(this, options, function (key, value) {
        if (allowUnknownKeys || this.keys.hasOwnProperty(key) ||
            AWS.Service.hasService(key)) {
          this.set(key, value);
        }
      });
    },
  
    /**
     * Loads configuration data from a JSON file into this config object.
     * @note Loading configuration will reset all existing configuration
     *   on the object.
     * @!macro nobrowser
     * @param path [String] the path relative to your process's current
     *    working directory to load configuration from.
     * @return [AWS.Config] the same configuration object
     */
    loadFromPath: function loadFromPath(path) {
      this.clear();
  
      var options = JSON.parse(AWS.util.readFileSync(path));
      var fileSystemCreds = new AWS.FileSystemCredentials(path);
      var chain = new AWS.CredentialProviderChain();
      chain.providers.unshift(fileSystemCreds);
      chain.resolve(function (err, creds) {
        if (err) throw err;
        else options.credentials = creds;
      });
  
      this.constructor(options);
  
      return this;
    },
  
    /**
     * Clears configuration data on this object
     *
     * @api private
     */
    clear: function clear() {
      /*jshint forin:false */
      AWS.util.each.call(this, this.keys, function (key) {
        delete this[key];
      });
  
      // reset credential provider
      this.set('credentials', undefined);
      this.set('credentialProvider', undefined);
    },
  
    /**
     * Sets a property on the configuration object, allowing for a
     * default value
     * @api private
     */
    set: function set(property, value, defaultValue) {
      if (value === undefined) {
        if (defaultValue === undefined) {
          defaultValue = this.keys[property];
        }
        if (typeof defaultValue === 'function') {
          this[property] = defaultValue.call(this);
        } else {
          this[property] = defaultValue;
        }
      } else if (property === 'httpOptions' && this[property]) {
        // deep merge httpOptions
        this[property] = AWS.util.merge(this[property], value);
      } else {
        this[property] = value;
      }
    },
  
    /**
     * All of the keys with their default values.
     *
     * @constant
     * @api private
     */
    keys: {
      credentials: null,
      credentialProvider: null,
      region: null,
      logger: null,
      apiVersions: {},
      apiVersion: null,
      endpoint: undefined,
      httpOptions: {
        timeout: 120000
      },
      maxRetries: undefined,
      maxRedirects: 10,
      paramValidation: true,
      sslEnabled: true,
      s3ForcePathStyle: false,
      s3BucketEndpoint: false,
      computeChecksums: true,
      convertResponseTypes: true,
      correctClockSkew: false,
      dynamoDbCrc32: true,
      systemClockOffset: 0,
      signatureVersion: null,
      signatureCache: true
    },
  
    /**
     * Extracts accessKeyId, secretAccessKey and sessionToken
     * from a configuration hash.
     *
     * @api private
     */
    extractCredentials: function extractCredentials(options) {
      if (options.accessKeyId && options.secretAccessKey) {
        options = AWS.util.copy(options);
        options.credentials = new AWS.Credentials(options);
      }
      return options;
    }
  });
  
  /**
   * @return [AWS.Config] The global configuration object singleton instance
   * @readonly
   * @see AWS.Config
   */
  AWS.config = new AWS.Config();
  