/*
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 *
 * Code generated by Microsoft (R) AutoRest Code Generator.
 * Changes may cause incorrect behavior and will be lost if the code is
 * regenerated.
 */

/* jshint latedef:false */
/* jshint forin:false */
/* jshint noempty:false */

'use strict';

const msRest = require('ms-rest');
const ServiceClient = msRest.ServiceClient;
const WebResource = msRest.WebResource;

const models = require('./models');


/**
 * This operation extracts a rich set of visual features based on the image
 * content.
 * Two input methods are supported -- (1) Uploading an image or (2) specifying
 * an image URL. Within your request, there is an optional parameter to allow
 * you to choose which features to return. By default, image categories are
 * returned in the response.
 * A successful response will be returned in JSON. If the request failed, the
 * response will contain an error code and a message to help understand what
 * went wrong.
 *
 * @param {string} url Publicly reachable URL of an image.
 *
 * @param {object} [options] Optional Parameters.
 *
 * @param {array} [options.visualFeatures] A string indicating what visual
 * feature types to return. Multiple values should be comma-separated. Valid
 * visual feature types include: Categories - categorizes image content
 * according to a taxonomy defined in documentation. Tags - tags the image with
 * a detailed list of words related to the image content. Description -
 * describes the image content with a complete English sentence. Faces -
 * detects if faces are present. If present, generate coordinates, gender and
 * age. ImageType - detects if image is clipart or a line drawing. Color -
 * determines the accent color, dominant color, and whether an image is
 * black&white. Adult - detects if the image is pornographic in nature (depicts
 * nudity or a sex act).  Sexually suggestive content is also detected. Objects
 * - detects various objects within an image, including the approximate
 * location. The Objects argument is only available in English. Brands -
 * detects various brands within an image, including the approximate location.
 * The Brands argument is only available in English.
 *
 * @param {array} [options.details] A string indicating which domain-specific
 * details to return. Multiple values should be comma-separated. Valid visual
 * feature types include: Celebrities - identifies celebrities if detected in
 * the image, Landmarks - identifies notable landmarks in the image.
 *
 * @param {string} [options.language] The desired language for output
 * generation. If this parameter is not specified, the default value is
 * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
 * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
 * 'en', 'es', 'ja', 'pt', 'zh'
 *
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 *
 * @param {function} callback - The callback.
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object if an error did not occur.
 *                      See {@link ImageAnalysis} for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
function _analyzeImage(url, options, callback) {
   /* jshint validthis: true */
  let client = this;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  let visualFeatures = (options && options.visualFeatures !== undefined) ? options.visualFeatures : undefined;
  let details = (options && options.details !== undefined) ? options.details : undefined;
  let language = (options && options.language !== undefined) ? options.language : 'en';
  // Validate
  try {
    if (this.endpoint === null || this.endpoint === undefined || typeof this.endpoint.valueOf() !== 'string') {
      throw new Error('this.endpoint cannot be null or undefined and it must be of type string.');
    }
    if (Array.isArray(visualFeatures)) {
      for (let i = 0; i < visualFeatures.length; i++) {
        if (visualFeatures[i]) {
          let allowedValues = [ 'ImageType', 'Faces', 'Adult', 'Categories', 'Color', 'Tags', 'Description', 'Objects', 'Brands' ];
          if (!allowedValues.some( function(item) { return item === visualFeatures[i]; })) {
            throw new Error(visualFeatures[i] + ' is not a valid value. The valid values are: ' + allowedValues);
          }
        }
      }
    }
    if (Array.isArray(details)) {
      for (let i1 = 0; i1 < details.length; i1++) {
        if (details[i1]) {
          let allowedValues1 = [ 'Celebrities', 'Landmarks' ];
          if (!allowedValues1.some( function(item) { return item === details[i1]; })) {
            throw new Error(details[i1] + ' is not a valid value. The valid values are: ' + allowedValues1);
          }
        }
      }
    }
    if (language !== null && language !== undefined && typeof language.valueOf() !== 'string') {
      throw new Error('language must be of type string.');
    }
    if (url === null || url === undefined || typeof url.valueOf() !== 'string') {
      throw new Error('url cannot be null or undefined and it must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  let imageUrl;
  if (url !== null && url !== undefined) {
    imageUrl = new client.models['ImageUrl']();
    imageUrl.url = url;
  }

  // Construct URL
  let baseUrl = this.baseUri;
  let requestUrl = baseUrl + (baseUrl.endsWith('/') ? '' : '/') + 'analyze';
  requestUrl = requestUrl.replace('{Endpoint}', this.endpoint);
  let queryParameters = [];
  if (visualFeatures !== null && visualFeatures !== undefined) {
    queryParameters.push('visualFeatures=' + encodeURIComponent(visualFeatures.join(',')));
  }
  if (details !== null && details !== undefined) {
    queryParameters.push('details=' + encodeURIComponent(details.join(',')));
  }
  if (language !== null && language !== undefined) {
    queryParameters.push('language=' + encodeURIComponent(language));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }

  // Create HTTP transport objects
  let httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.url = requestUrl;
  httpRequest.headers = {};
  // Set Headers
  httpRequest.headers['Content-Type'] = 'application/json; charset=utf-8';
  if(options) {
    for(let headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  // Serialize Request
  let requestContent = null;
  let requestModel = null;
  try {
    if (imageUrl !== null && imageUrl !== undefined) {
      let requestModelMapper = new client.models['ImageUrl']().mapper();
      requestModel = client.serialize(requestModelMapper, imageUrl, 'imageUrl');
      requestContent = JSON.stringify(requestModel);
    }
  } catch (error) {
    let serializationError = new Error(`Error "${error.message}" occurred in serializing the ` +
        `payload - ${JSON.stringify(imageUrl, null, 2)}.`);
    return callback(serializationError);
  }
  httpRequest.body = requestContent;
  // Send Request
  return client.pipeline(httpRequest, (err, response, responseBody) => {
    if (err) {
      return callback(err);
    }
    let statusCode = response.statusCode;
    if (statusCode !== 200) {
      let error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      let parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          let internalError = null;
          if (parsedErrorResponse.error) internalError = parsedErrorResponse.error;
          error.code = internalError ? internalError.code : parsedErrorResponse.code;
          error.message = internalError ? internalError.message : parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          let resultMapper = new client.models['ComputerVisionError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody ` +
                         `- "${responseBody}" for the default response.`;
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    let result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      let parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          let resultMapper = new client.models['ImageAnalysis']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        let deserializationError = new Error(`Error ${error} occurred in deserializing the responseBody - ${responseBody}`);
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
}

/**
 * This operation generates a description of an image in human readable
 * language with complete sentences. The description is based on a collection
 * of content tags, which are also returned by the operation. More than one
 * description can be generated for each image. Descriptions are ordered by
 * their confidence score. All descriptions are in English.
 * Two input methods are supported -- (1) Uploading an image or (2) specifying
 * an image URL.
 * A successful response will be returned in JSON. If the request failed, the
 * response will contain an error code and a message to help understand what
 * went wrong.
 *
 * @param {string} url Publicly reachable URL of an image.
 *
 * @param {object} [options] Optional Parameters.
 *
 * @param {number} [options.maxCandidates] Maximum number of candidate
 * descriptions to be returned.  The default is 1.
 *
 * @param {string} [options.language] The desired language for output
 * generation. If this parameter is not specified, the default value is
 * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
 * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
 * 'en', 'es', 'ja', 'pt', 'zh'
 *
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 *
 * @param {function} callback - The callback.
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object if an error did not occur.
 *                      See {@link ImageDescription} for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
function _describeImage(url, options, callback) {
   /* jshint validthis: true */
  let client = this;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  let maxCandidates = (options && options.maxCandidates !== undefined) ? options.maxCandidates : 1;
  let language = (options && options.language !== undefined) ? options.language : 'en';
  // Validate
  try {
    if (this.endpoint === null || this.endpoint === undefined || typeof this.endpoint.valueOf() !== 'string') {
      throw new Error('this.endpoint cannot be null or undefined and it must be of type string.');
    }
    if (maxCandidates !== null && maxCandidates !== undefined && typeof maxCandidates !== 'number') {
      throw new Error('maxCandidates must be of type number.');
    }
    if (language !== null && language !== undefined && typeof language.valueOf() !== 'string') {
      throw new Error('language must be of type string.');
    }
    if (url === null || url === undefined || typeof url.valueOf() !== 'string') {
      throw new Error('url cannot be null or undefined and it must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  let imageUrl;
  if (url !== null && url !== undefined) {
    imageUrl = new client.models['ImageUrl']();
    imageUrl.url = url;
  }

  // Construct URL
  let baseUrl = this.baseUri;
  let requestUrl = baseUrl + (baseUrl.endsWith('/') ? '' : '/') + 'describe';
  requestUrl = requestUrl.replace('{Endpoint}', this.endpoint);
  let queryParameters = [];
  if (maxCandidates !== null && maxCandidates !== undefined) {
    queryParameters.push('maxCandidates=' + encodeURIComponent(maxCandidates.toString()));
  }
  if (language !== null && language !== undefined) {
    queryParameters.push('language=' + encodeURIComponent(language));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }

  // Create HTTP transport objects
  let httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.url = requestUrl;
  httpRequest.headers = {};
  // Set Headers
  httpRequest.headers['Content-Type'] = 'application/json; charset=utf-8';
  if(options) {
    for(let headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  // Serialize Request
  let requestContent = null;
  let requestModel = null;
  try {
    if (imageUrl !== null && imageUrl !== undefined) {
      let requestModelMapper = new client.models['ImageUrl']().mapper();
      requestModel = client.serialize(requestModelMapper, imageUrl, 'imageUrl');
      requestContent = JSON.stringify(requestModel);
    }
  } catch (error) {
    let serializationError = new Error(`Error "${error.message}" occurred in serializing the ` +
        `payload - ${JSON.stringify(imageUrl, null, 2)}.`);
    return callback(serializationError);
  }
  httpRequest.body = requestContent;
  // Send Request
  return client.pipeline(httpRequest, (err, response, responseBody) => {
    if (err) {
      return callback(err);
    }
    let statusCode = response.statusCode;
    if (statusCode !== 200) {
      let error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      let parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          let internalError = null;
          if (parsedErrorResponse.error) internalError = parsedErrorResponse.error;
          error.code = internalError ? internalError.code : parsedErrorResponse.code;
          error.message = internalError ? internalError.message : parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          let resultMapper = new client.models['ComputerVisionError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody ` +
                         `- "${responseBody}" for the default response.`;
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    let result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      let parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          let resultMapper = new client.models['ImageDescription']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        let deserializationError = new Error(`Error ${error} occurred in deserializing the responseBody - ${responseBody}`);
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
}

/**
 * Performs object detection on the specified image.
 * Two input methods are supported -- (1) Uploading an image or (2) specifying
 * an image URL.
 * A successful response will be returned in JSON. If the request failed, the
 * response will contain an error code and a message to help understand what
 * went wrong.
 *
 * @param {string} url Publicly reachable URL of an image.
 *
 * @param {object} [options] Optional Parameters.
 *
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 *
 * @param {function} callback - The callback.
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object if an error did not occur.
 *                      See {@link DetectResult} for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
function _detectObjects(url, options, callback) {
   /* jshint validthis: true */
  let client = this;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  // Validate
  try {
    if (this.endpoint === null || this.endpoint === undefined || typeof this.endpoint.valueOf() !== 'string') {
      throw new Error('this.endpoint cannot be null or undefined and it must be of type string.');
    }
    if (url === null || url === undefined || typeof url.valueOf() !== 'string') {
      throw new Error('url cannot be null or undefined and it must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  let imageUrl;
  if (url !== null && url !== undefined) {
    imageUrl = new client.models['ImageUrl']();
    imageUrl.url = url;
  }

  // Construct URL
  let baseUrl = this.baseUri;
  let requestUrl = baseUrl + (baseUrl.endsWith('/') ? '' : '/') + 'detect';
  requestUrl = requestUrl.replace('{Endpoint}', this.endpoint);

  // Create HTTP transport objects
  let httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.url = requestUrl;
  httpRequest.headers = {};
  // Set Headers
  httpRequest.headers['Content-Type'] = 'application/json; charset=utf-8';
  if(options) {
    for(let headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  // Serialize Request
  let requestContent = null;
  let requestModel = null;
  try {
    if (imageUrl !== null && imageUrl !== undefined) {
      let requestModelMapper = new client.models['ImageUrl']().mapper();
      requestModel = client.serialize(requestModelMapper, imageUrl, 'imageUrl');
      requestContent = JSON.stringify(requestModel);
    }
  } catch (error) {
    let serializationError = new Error(`Error "${error.message}" occurred in serializing the ` +
        `payload - ${JSON.stringify(imageUrl, null, 2)}.`);
    return callback(serializationError);
  }
  httpRequest.body = requestContent;
  // Send Request
  return client.pipeline(httpRequest, (err, response, responseBody) => {
    if (err) {
      return callback(err);
    }
    let statusCode = response.statusCode;
    if (statusCode !== 200) {
      let error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      let parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          let internalError = null;
          if (parsedErrorResponse.error) internalError = parsedErrorResponse.error;
          error.code = internalError ? internalError.code : parsedErrorResponse.code;
          error.message = internalError ? internalError.message : parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          let resultMapper = new client.models['ComputerVisionError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody ` +
                         `- "${responseBody}" for the default response.`;
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    let result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      let parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          let resultMapper = new client.models['DetectResult']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        let deserializationError = new Error(`Error ${error} occurred in deserializing the responseBody - ${responseBody}`);
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
}

/**
 * This operation returns the list of domain-specific models that are supported
 * by the Computer Vision API. Currently, the API supports following
 * domain-specific models: celebrity recognizer, landmark recognizer.
 * A successful response will be returned in JSON. If the request failed, the
 * response will contain an error code and a message to help understand what
 * went wrong.
 *
 * @param {object} [options] Optional Parameters.
 *
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 *
 * @param {function} callback - The callback.
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object if an error did not occur.
 *                      See {@link ListModelsResult} for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
function _listModels(options, callback) {
   /* jshint validthis: true */
  let client = this;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  // Validate
  try {
    if (this.endpoint === null || this.endpoint === undefined || typeof this.endpoint.valueOf() !== 'string') {
      throw new Error('this.endpoint cannot be null or undefined and it must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  let baseUrl = this.baseUri;
  let requestUrl = baseUrl + (baseUrl.endsWith('/') ? '' : '/') + 'models';
  requestUrl = requestUrl.replace('{Endpoint}', this.endpoint);

  // Create HTTP transport objects
  let httpRequest = new WebResource();
  httpRequest.method = 'GET';
  httpRequest.url = requestUrl;
  httpRequest.headers = {};
  // Set Headers
  httpRequest.headers['Content-Type'] = 'application/json; charset=utf-8';
  if(options) {
    for(let headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  httpRequest.body = null;
  // Send Request
  return client.pipeline(httpRequest, (err, response, responseBody) => {
    if (err) {
      return callback(err);
    }
    let statusCode = response.statusCode;
    if (statusCode !== 200) {
      let error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      let parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          let internalError = null;
          if (parsedErrorResponse.error) internalError = parsedErrorResponse.error;
          error.code = internalError ? internalError.code : parsedErrorResponse.code;
          error.message = internalError ? internalError.message : parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          let resultMapper = new client.models['ComputerVisionError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody ` +
                         `- "${responseBody}" for the default response.`;
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    let result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      let parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          let resultMapper = new client.models['ListModelsResult']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        let deserializationError = new Error(`Error ${error} occurred in deserializing the responseBody - ${responseBody}`);
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
}

/**
 * This operation recognizes content within an image by applying a
 * domain-specific model. The list of domain-specific models that are supported
 * by the Computer Vision API can be retrieved using the /models GET request.
 * Currently, the API provides following domain-specific models: celebrities,
 * landmarks.
 * Two input methods are supported -- (1) Uploading an image or (2) specifying
 * an image URL.
 * A successful response will be returned in JSON.
 * If the request failed, the response will contain an error code and a message
 * to help understand what went wrong.
 *
 * @param {string} model The domain-specific content to recognize.
 *
 * @param {string} url Publicly reachable URL of an image.
 *
 * @param {object} [options] Optional Parameters.
 *
 * @param {string} [options.language] The desired language for output
 * generation. If this parameter is not specified, the default value is
 * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
 * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
 * 'en', 'es', 'ja', 'pt', 'zh'
 *
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 *
 * @param {function} callback - The callback.
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object if an error did not occur.
 *                      See {@link DomainModelResults} for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
function _analyzeImageByDomain(model, url, options, callback) {
   /* jshint validthis: true */
  let client = this;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  let language = (options && options.language !== undefined) ? options.language : 'en';
  // Validate
  try {
    if (this.endpoint === null || this.endpoint === undefined || typeof this.endpoint.valueOf() !== 'string') {
      throw new Error('this.endpoint cannot be null or undefined and it must be of type string.');
    }
    if (model === null || model === undefined || typeof model.valueOf() !== 'string') {
      throw new Error('model cannot be null or undefined and it must be of type string.');
    }
    if (language !== null && language !== undefined && typeof language.valueOf() !== 'string') {
      throw new Error('language must be of type string.');
    }
    if (url === null || url === undefined || typeof url.valueOf() !== 'string') {
      throw new Error('url cannot be null or undefined and it must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  let imageUrl;
  if (url !== null && url !== undefined) {
    imageUrl = new client.models['ImageUrl']();
    imageUrl.url = url;
  }

  // Construct URL
  let baseUrl = this.baseUri;
  let requestUrl = baseUrl + (baseUrl.endsWith('/') ? '' : '/') + 'models/{model}/analyze';
  requestUrl = requestUrl.replace('{Endpoint}', this.endpoint);
  requestUrl = requestUrl.replace('{model}', encodeURIComponent(model));
  let queryParameters = [];
  if (language !== null && language !== undefined) {
    queryParameters.push('language=' + encodeURIComponent(language));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }

  // Create HTTP transport objects
  let httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.url = requestUrl;
  httpRequest.headers = {};
  // Set Headers
  httpRequest.headers['Content-Type'] = 'application/json; charset=utf-8';
  if(options) {
    for(let headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  // Serialize Request
  let requestContent = null;
  let requestModel = null;
  try {
    if (imageUrl !== null && imageUrl !== undefined) {
      let requestModelMapper = new client.models['ImageUrl']().mapper();
      requestModel = client.serialize(requestModelMapper, imageUrl, 'imageUrl');
      requestContent = JSON.stringify(requestModel);
    }
  } catch (error) {
    let serializationError = new Error(`Error "${error.message}" occurred in serializing the ` +
        `payload - ${JSON.stringify(imageUrl, null, 2)}.`);
    return callback(serializationError);
  }
  httpRequest.body = requestContent;
  // Send Request
  return client.pipeline(httpRequest, (err, response, responseBody) => {
    if (err) {
      return callback(err);
    }
    let statusCode = response.statusCode;
    if (statusCode !== 200) {
      let error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      let parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          let internalError = null;
          if (parsedErrorResponse.error) internalError = parsedErrorResponse.error;
          error.code = internalError ? internalError.code : parsedErrorResponse.code;
          error.message = internalError ? internalError.message : parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          let resultMapper = new client.models['ComputerVisionError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody ` +
                         `- "${responseBody}" for the default response.`;
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    let result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      let parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          let resultMapper = new client.models['DomainModelResults']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        let deserializationError = new Error(`Error ${error} occurred in deserializing the responseBody - ${responseBody}`);
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
}

/**
 * Optical Character Recognition (OCR) detects text in an image and extracts
 * the recognized characters into a machine-usable character stream.
 * Upon success, the OCR results will be returned.
 * Upon failure, the error code together with an error message will be
 * returned. The error code can be one of InvalidImageUrl, InvalidImageFormat,
 * InvalidImageSize, NotSupportedImage, NotSupportedLanguage, or
 * InternalServerError.
 *
 * @param {boolean} detectOrientation Whether detect the text orientation in
 * the image. With detectOrientation=true the OCR service tries to detect the
 * image orientation and correct it before further processing (e.g. if it's
 * upside-down).
 *
 * @param {string} url Publicly reachable URL of an image.
 *
 * @param {object} [options] Optional Parameters.
 *
 * @param {string} [options.language] The BCP-47 language code of the text to
 * be detected in the image. The default value is 'unk'. Possible values
 * include: 'unk', 'zh-Hans', 'zh-Hant', 'cs', 'da', 'nl', 'en', 'fi', 'fr',
 * 'de', 'el', 'hu', 'it', 'ja', 'ko', 'nb', 'pl', 'pt', 'ru', 'es', 'sv',
 * 'tr', 'ar', 'ro', 'sr-Cyrl', 'sr-Latn', 'sk'
 *
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 *
 * @param {function} callback - The callback.
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object if an error did not occur.
 *                      See {@link OcrResult} for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
function _recognizePrintedText(detectOrientation, url, options, callback) {
   /* jshint validthis: true */
  let client = this;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  let language = (options && options.language !== undefined) ? options.language : 'unk';
  // Validate
  try {
    if (this.endpoint === null || this.endpoint === undefined || typeof this.endpoint.valueOf() !== 'string') {
      throw new Error('this.endpoint cannot be null or undefined and it must be of type string.');
    }
    if (detectOrientation === null || detectOrientation === undefined || typeof detectOrientation !== 'boolean') {
      throw new Error('detectOrientation cannot be null or undefined and it must be of type boolean.');
    }
    if (language) {
      let allowedValues = [ 'unk', 'zh-Hans', 'zh-Hant', 'cs', 'da', 'nl', 'en', 'fi', 'fr', 'de', 'el', 'hu', 'it', 'ja', 'ko', 'nb', 'pl', 'pt', 'ru', 'es', 'sv', 'tr', 'ar', 'ro', 'sr-Cyrl', 'sr-Latn', 'sk' ];
      if (!allowedValues.some( function(item) { return item === language; })) {
        throw new Error(language + ' is not a valid value. The valid values are: ' + allowedValues);
      }
    }
    if (url === null || url === undefined || typeof url.valueOf() !== 'string') {
      throw new Error('url cannot be null or undefined and it must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  let imageUrl;
  if (url !== null && url !== undefined) {
    imageUrl = new client.models['ImageUrl']();
    imageUrl.url = url;
  }

  // Construct URL
  let baseUrl = this.baseUri;
  let requestUrl = baseUrl + (baseUrl.endsWith('/') ? '' : '/') + 'ocr';
  requestUrl = requestUrl.replace('{Endpoint}', this.endpoint);
  let queryParameters = [];
  queryParameters.push('detectOrientation=' + encodeURIComponent(detectOrientation.toString()));
  if (language !== null && language !== undefined) {
    queryParameters.push('language=' + encodeURIComponent(language));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }

  // Create HTTP transport objects
  let httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.url = requestUrl;
  httpRequest.headers = {};
  // Set Headers
  httpRequest.headers['Content-Type'] = 'application/json; charset=utf-8';
  if(options) {
    for(let headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  // Serialize Request
  let requestContent = null;
  let requestModel = null;
  try {
    if (imageUrl !== null && imageUrl !== undefined) {
      let requestModelMapper = new client.models['ImageUrl']().mapper();
      requestModel = client.serialize(requestModelMapper, imageUrl, 'imageUrl');
      requestContent = JSON.stringify(requestModel);
    }
  } catch (error) {
    let serializationError = new Error(`Error "${error.message}" occurred in serializing the ` +
        `payload - ${JSON.stringify(imageUrl, null, 2)}.`);
    return callback(serializationError);
  }
  httpRequest.body = requestContent;
  // Send Request
  return client.pipeline(httpRequest, (err, response, responseBody) => {
    if (err) {
      return callback(err);
    }
    let statusCode = response.statusCode;
    if (statusCode !== 200) {
      let error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      let parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          let internalError = null;
          if (parsedErrorResponse.error) internalError = parsedErrorResponse.error;
          error.code = internalError ? internalError.code : parsedErrorResponse.code;
          error.message = internalError ? internalError.message : parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          let resultMapper = new client.models['ComputerVisionError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody ` +
                         `- "${responseBody}" for the default response.`;
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    let result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      let parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          let resultMapper = new client.models['OcrResult']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        let deserializationError = new Error(`Error ${error} occurred in deserializing the responseBody - ${responseBody}`);
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
}

/**
 * This operation generates a list of words, or tags, that are relevant to the
 * content of the supplied image. The Computer Vision API can return tags based
 * on objects, living beings, scenery or actions found in images. Unlike
 * categories, tags are not organized according to a hierarchical
 * classification system, but correspond to image content. Tags may contain
 * hints to avoid ambiguity or provide context, for example the tag "cello" may
 * be accompanied by the hint "musical instrument". All tags are in English.
 * Two input methods are supported -- (1) Uploading an image or (2) specifying
 * an image URL.
 * A successful response will be returned in JSON. If the request failed, the
 * response will contain an error code and a message to help understand what
 * went wrong.
 *
 * @param {string} url Publicly reachable URL of an image.
 *
 * @param {object} [options] Optional Parameters.
 *
 * @param {string} [options.language] The desired language for output
 * generation. If this parameter is not specified, the default value is
 * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
 * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
 * 'en', 'es', 'ja', 'pt', 'zh'
 *
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 *
 * @param {function} callback - The callback.
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object if an error did not occur.
 *                      See {@link TagResult} for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
function _tagImage(url, options, callback) {
   /* jshint validthis: true */
  let client = this;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  let language = (options && options.language !== undefined) ? options.language : 'en';
  // Validate
  try {
    if (this.endpoint === null || this.endpoint === undefined || typeof this.endpoint.valueOf() !== 'string') {
      throw new Error('this.endpoint cannot be null or undefined and it must be of type string.');
    }
    if (language !== null && language !== undefined && typeof language.valueOf() !== 'string') {
      throw new Error('language must be of type string.');
    }
    if (url === null || url === undefined || typeof url.valueOf() !== 'string') {
      throw new Error('url cannot be null or undefined and it must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  let imageUrl;
  if (url !== null && url !== undefined) {
    imageUrl = new client.models['ImageUrl']();
    imageUrl.url = url;
  }

  // Construct URL
  let baseUrl = this.baseUri;
  let requestUrl = baseUrl + (baseUrl.endsWith('/') ? '' : '/') + 'tag';
  requestUrl = requestUrl.replace('{Endpoint}', this.endpoint);
  let queryParameters = [];
  if (language !== null && language !== undefined) {
    queryParameters.push('language=' + encodeURIComponent(language));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }

  // Create HTTP transport objects
  let httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.url = requestUrl;
  httpRequest.headers = {};
  // Set Headers
  httpRequest.headers['Content-Type'] = 'application/json; charset=utf-8';
  if(options) {
    for(let headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  // Serialize Request
  let requestContent = null;
  let requestModel = null;
  try {
    if (imageUrl !== null && imageUrl !== undefined) {
      let requestModelMapper = new client.models['ImageUrl']().mapper();
      requestModel = client.serialize(requestModelMapper, imageUrl, 'imageUrl');
      requestContent = JSON.stringify(requestModel);
    }
  } catch (error) {
    let serializationError = new Error(`Error "${error.message}" occurred in serializing the ` +
        `payload - ${JSON.stringify(imageUrl, null, 2)}.`);
    return callback(serializationError);
  }
  httpRequest.body = requestContent;
  // Send Request
  return client.pipeline(httpRequest, (err, response, responseBody) => {
    if (err) {
      return callback(err);
    }
    let statusCode = response.statusCode;
    if (statusCode !== 200) {
      let error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      let parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          let internalError = null;
          if (parsedErrorResponse.error) internalError = parsedErrorResponse.error;
          error.code = internalError ? internalError.code : parsedErrorResponse.code;
          error.message = internalError ? internalError.message : parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          let resultMapper = new client.models['ComputerVisionError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody ` +
                         `- "${responseBody}" for the default response.`;
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    let result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      let parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          let resultMapper = new client.models['TagResult']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        let deserializationError = new Error(`Error ${error} occurred in deserializing the responseBody - ${responseBody}`);
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
}

/**
 * This operation generates a thumbnail image with the user-specified width and
 * height. By default, the service analyzes the image, identifies the region of
 * interest (ROI), and generates smart cropping coordinates based on the ROI.
 * Smart cropping helps when you specify an aspect ratio that differs from that
 * of the input image.
 * A successful response contains the thumbnail image binary. If the request
 * failed, the response contains an error code and a message to help determine
 * what went wrong.
 * Upon failure, the error code and an error message are returned. The error
 * code could be one of InvalidImageUrl, InvalidImageFormat, InvalidImageSize,
 * InvalidThumbnailSize, NotSupportedImage, FailedToProcess, Timeout, or
 * InternalServerError.
 *
 * @param {number} width Width of the thumbnail, in pixels. It must be between
 * 1 and 1024. Recommended minimum of 50.
 *
 * @param {number} height Height of the thumbnail, in pixels. It must be
 * between 1 and 1024. Recommended minimum of 50.
 *
 * @param {string} url Publicly reachable URL of an image.
 *
 * @param {object} [options] Optional Parameters.
 *
 * @param {boolean} [options.smartCropping] Boolean flag for enabling smart
 * cropping.
 *
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 *
 * @param {function} callback - The callback.
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object if an error did not occur.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
function _generateThumbnail(width, height, url, options, callback) {
   /* jshint validthis: true */
  let client = this;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  let smartCropping = (options && options.smartCropping !== undefined) ? options.smartCropping : false;
  // Validate
  try {
    if (this.endpoint === null || this.endpoint === undefined || typeof this.endpoint.valueOf() !== 'string') {
      throw new Error('this.endpoint cannot be null or undefined and it must be of type string.');
    }
    if (width === null || width === undefined || typeof width !== 'number') {
      throw new Error('width cannot be null or undefined and it must be of type number.');
    }
    if (width !== null && width !== undefined) {
      if (width > 1024)
      {
        throw new Error('"width" should satisfy the constraint - "InclusiveMaximum": 1024');
      }
      if (width < 1)
      {
        throw new Error('"width" should satisfy the constraint - "InclusiveMinimum": 1');
      }
    }
    if (height === null || height === undefined || typeof height !== 'number') {
      throw new Error('height cannot be null or undefined and it must be of type number.');
    }
    if (height !== null && height !== undefined) {
      if (height > 1024)
      {
        throw new Error('"height" should satisfy the constraint - "InclusiveMaximum": 1024');
      }
      if (height < 1)
      {
        throw new Error('"height" should satisfy the constraint - "InclusiveMinimum": 1');
      }
    }
    if (smartCropping !== null && smartCropping !== undefined && typeof smartCropping !== 'boolean') {
      throw new Error('smartCropping must be of type boolean.');
    }
    if (url === null || url === undefined || typeof url.valueOf() !== 'string') {
      throw new Error('url cannot be null or undefined and it must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  let imageUrl;
  if (url !== null && url !== undefined) {
    imageUrl = new client.models['ImageUrl']();
    imageUrl.url = url;
  }

  // Construct URL
  let baseUrl = this.baseUri;
  let requestUrl = baseUrl + (baseUrl.endsWith('/') ? '' : '/') + 'generateThumbnail';
  requestUrl = requestUrl.replace('{Endpoint}', this.endpoint);
  let queryParameters = [];
  queryParameters.push('width=' + encodeURIComponent(width.toString()));
  queryParameters.push('height=' + encodeURIComponent(height.toString()));
  if (smartCropping !== null && smartCropping !== undefined) {
    queryParameters.push('smartCropping=' + encodeURIComponent(smartCropping.toString()));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }

  // Create HTTP transport objects
  let httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.url = requestUrl;
  httpRequest.headers = {};
  // Set Headers
  httpRequest.headers['Content-Type'] = 'application/json; charset=utf-8';
  if(options) {
    for(let headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  // Serialize Request
  let requestContent = null;
  let requestModel = null;
  try {
    if (imageUrl !== null && imageUrl !== undefined) {
      let requestModelMapper = new client.models['ImageUrl']().mapper();
      requestModel = client.serialize(requestModelMapper, imageUrl, 'imageUrl');
      requestContent = JSON.stringify(requestModel);
    }
  } catch (error) {
    let serializationError = new Error(`Error "${error.message}" occurred in serializing the ` +
        `payload - ${JSON.stringify(imageUrl, null, 2)}.`);
    return callback(serializationError);
  }
  httpRequest.body = requestContent;
  // Send Request
  httpRequest.streamedResponse = true;
  return client.pipeline(httpRequest, (err, response, responseBody) => {
    if (err) {
      return callback(err);
    }

    let statusCode = response.statusCode;
    if (statusCode !== 200) {
      let error = new Error(`Unexpected status code: ${statusCode}`);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      let parsedErrorResponse;
      try {
        if (responseBody !== undefined) parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          let internalError = null;
          if (parsedErrorResponse.error) internalError = parsedErrorResponse.error;
          error.code = internalError ? internalError.code : parsedErrorResponse.code;
          error.message = internalError ? internalError.message : parsedErrorResponse.message;
        }
      } catch (defaultError) {
        error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody ` +
                         `- "${responseBody}" for the default response.`;
        return callback(error);
      }
      return callback(error);
    }

    // Create Result
    let result = response;
    return callback(null, result, httpRequest, response);
  });
}

/**
 * This operation returns a bounding box around the most important area of the
 * image.
 * A successful response will be returned in JSON. If the request failed, the
 * response contains an error code and a message to help determine what went
 * wrong.
 * Upon failure, the error code and an error message are returned. The error
 * code could be one of InvalidImageUrl, InvalidImageFormat, InvalidImageSize,
 * NotSupportedImage, FailedToProcess, Timeout, or InternalServerError.
 *
 * @param {string} url Publicly reachable URL of an image.
 *
 * @param {object} [options] Optional Parameters.
 *
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 *
 * @param {function} callback - The callback.
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object if an error did not occur.
 *                      See {@link AreaOfInterestResult} for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
function _getAreaOfInterest(url, options, callback) {
   /* jshint validthis: true */
  let client = this;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  // Validate
  try {
    if (this.endpoint === null || this.endpoint === undefined || typeof this.endpoint.valueOf() !== 'string') {
      throw new Error('this.endpoint cannot be null or undefined and it must be of type string.');
    }
    if (url === null || url === undefined || typeof url.valueOf() !== 'string') {
      throw new Error('url cannot be null or undefined and it must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  let imageUrl;
  if (url !== null && url !== undefined) {
    imageUrl = new client.models['ImageUrl']();
    imageUrl.url = url;
  }

  // Construct URL
  let baseUrl = this.baseUri;
  let requestUrl = baseUrl + (baseUrl.endsWith('/') ? '' : '/') + 'areaOfInterest';
  requestUrl = requestUrl.replace('{Endpoint}', this.endpoint);

  // Create HTTP transport objects
  let httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.url = requestUrl;
  httpRequest.headers = {};
  // Set Headers
  httpRequest.headers['Content-Type'] = 'application/json; charset=utf-8';
  if(options) {
    for(let headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  // Serialize Request
  let requestContent = null;
  let requestModel = null;
  try {
    if (imageUrl !== null && imageUrl !== undefined) {
      let requestModelMapper = new client.models['ImageUrl']().mapper();
      requestModel = client.serialize(requestModelMapper, imageUrl, 'imageUrl');
      requestContent = JSON.stringify(requestModel);
    }
  } catch (error) {
    let serializationError = new Error(`Error "${error.message}" occurred in serializing the ` +
        `payload - ${JSON.stringify(imageUrl, null, 2)}.`);
    return callback(serializationError);
  }
  httpRequest.body = requestContent;
  // Send Request
  return client.pipeline(httpRequest, (err, response, responseBody) => {
    if (err) {
      return callback(err);
    }
    let statusCode = response.statusCode;
    if (statusCode !== 200) {
      let error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      let parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          let internalError = null;
          if (parsedErrorResponse.error) internalError = parsedErrorResponse.error;
          error.code = internalError ? internalError.code : parsedErrorResponse.code;
          error.message = internalError ? internalError.message : parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          let resultMapper = new client.models['ComputerVisionError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody ` +
                         `- "${responseBody}" for the default response.`;
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    let result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      let parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          let resultMapper = new client.models['AreaOfInterestResult']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        let deserializationError = new Error(`Error ${error} occurred in deserializing the responseBody - ${responseBody}`);
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
}

/**
 * Recognize Text operation. When you use the Recognize Text interface, the
 * response contains a field called 'Operation-Location'. The
 * 'Operation-Location' field contains the URL that you must use for your Get
 * Recognize Text Operation Result operation.
 *
 * @param {string} mode Type of text to recognize. Possible values include:
 * 'Handwritten', 'Printed'
 *
 * @param {string} url Publicly reachable URL of an image.
 *
 * @param {object} [options] Optional Parameters.
 *
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 *
 * @param {function} callback - The callback.
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {null} [result]   - The deserialized result object if an error did not occur.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
function _recognizeText(url, mode, options, callback) {
   /* jshint validthis: true */
  let client = this;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  // Validate
  try {
    if (this.endpoint === null || this.endpoint === undefined || typeof this.endpoint.valueOf() !== 'string') {
      throw new Error('this.endpoint cannot be null or undefined and it must be of type string.');
    }
    if (mode) {
      let allowedValues = [ 'Handwritten', 'Printed' ];
      if (!allowedValues.some( function(item) { return item === mode; })) {
        throw new Error(mode + ' is not a valid value. The valid values are: ' + allowedValues);
      }
    } else {
      throw new Error('mode cannot be null or undefined.');
    }
    if (url === null || url === undefined || typeof url.valueOf() !== 'string') {
      throw new Error('url cannot be null or undefined and it must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  let imageUrl;
  if (url !== null && url !== undefined) {
    imageUrl = new client.models['ImageUrl']();
    imageUrl.url = url;
  }

  // Construct URL
  let baseUrl = this.baseUri;
  let requestUrl = baseUrl + (baseUrl.endsWith('/') ? '' : '/') + 'recognizeText';
  requestUrl = requestUrl.replace('{Endpoint}', this.endpoint);
  let queryParameters = [];
  queryParameters.push('mode=' + encodeURIComponent(mode));
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }

  // Create HTTP transport objects
  let httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.url = requestUrl;
  httpRequest.headers = {};
  // Set Headers
  httpRequest.headers['Content-Type'] = 'application/json; charset=utf-8';
  if(options) {
    for(let headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  // Serialize Request
  let requestContent = null;
  let requestModel = null;
  try {
    if (imageUrl !== null && imageUrl !== undefined) {
      let requestModelMapper = new client.models['ImageUrl']().mapper();
      requestModel = client.serialize(requestModelMapper, imageUrl, 'imageUrl');
      requestContent = JSON.stringify(requestModel);
    }
  } catch (error) {
    let serializationError = new Error(`Error "${error.message}" occurred in serializing the ` +
        `payload - ${JSON.stringify(imageUrl, null, 2)}.`);
    return callback(serializationError);
  }
  httpRequest.body = requestContent;
  // Send Request
  return client.pipeline(httpRequest, (err, response, responseBody) => {
    if (err) {
      return callback(err);
    }
    let statusCode = response.statusCode;
    if (statusCode !== 202) {
      let error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      let parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          let internalError = null;
          if (parsedErrorResponse.error) internalError = parsedErrorResponse.error;
          error.code = internalError ? internalError.code : parsedErrorResponse.code;
          error.message = internalError ? internalError.message : parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          let resultMapper = new client.models['ComputerVisionError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody ` +
                         `- "${responseBody}" for the default response.`;
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    let result = null;
    if (responseBody === '') responseBody = null;

    return callback(null, result, httpRequest, response);
  });
}

/**
 * This interface is used for getting text operation result. The URL to this
 * interface should be retrieved from 'Operation-Location' field returned from
 * Recognize Text interface.
 *
 * @param {string} operationId Id of the text operation returned in the
 * response of the 'Recognize Text'
 *
 * @param {object} [options] Optional Parameters.
 *
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 *
 * @param {function} callback - The callback.
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object if an error did not occur.
 *                      See {@link TextOperationResult} for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
function _getTextOperationResult(operationId, options, callback) {
   /* jshint validthis: true */
  let client = this;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  // Validate
  try {
    if (this.endpoint === null || this.endpoint === undefined || typeof this.endpoint.valueOf() !== 'string') {
      throw new Error('this.endpoint cannot be null or undefined and it must be of type string.');
    }
    if (operationId === null || operationId === undefined || typeof operationId.valueOf() !== 'string') {
      throw new Error('operationId cannot be null or undefined and it must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  let baseUrl = this.baseUri;
  let requestUrl = baseUrl + (baseUrl.endsWith('/') ? '' : '/') + 'textOperations/{operationId}';
  requestUrl = requestUrl.replace('{Endpoint}', this.endpoint);
  requestUrl = requestUrl.replace('{operationId}', encodeURIComponent(operationId));

  // Create HTTP transport objects
  let httpRequest = new WebResource();
  httpRequest.method = 'GET';
  httpRequest.url = requestUrl;
  httpRequest.headers = {};
  // Set Headers
  httpRequest.headers['Content-Type'] = 'application/json; charset=utf-8';
  if(options) {
    for(let headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  httpRequest.body = null;
  // Send Request
  return client.pipeline(httpRequest, (err, response, responseBody) => {
    if (err) {
      return callback(err);
    }
    let statusCode = response.statusCode;
    if (statusCode !== 200) {
      let error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      let parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          let internalError = null;
          if (parsedErrorResponse.error) internalError = parsedErrorResponse.error;
          error.code = internalError ? internalError.code : parsedErrorResponse.code;
          error.message = internalError ? internalError.message : parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          let resultMapper = new client.models['ComputerVisionError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody ` +
                         `- "${responseBody}" for the default response.`;
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    let result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      let parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          let resultMapper = new client.models['TextOperationResult']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        let deserializationError = new Error(`Error ${error} occurred in deserializing the responseBody - ${responseBody}`);
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
}

/**
 * Use this interface to get the result of a Read operation, employing the
 * state-of-the-art Optical Character Recognition (OCR) algorithms optimized
 * for text-heavy documents. When you use the Read File interface, the response
 * contains a field called "Operation-Location". The "Operation-Location" field
 * contains the URL that you must use for your "Read Operation Result"
 * operation to access OCR results.​
 *
 * @param {string} mode Type of text to recognize. Possible values include:
 * 'Handwritten', 'Printed'
 *
 * @param {string} url Publicly reachable URL of an image.
 *
 * @param {object} [options] Optional Parameters.
 *
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 *
 * @param {function} callback - The callback.
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {null} [result]   - The deserialized result object if an error did not occur.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
function _batchReadFile(url, mode, options, callback) {
   /* jshint validthis: true */
  let client = this;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  // Validate
  try {
    if (this.endpoint === null || this.endpoint === undefined || typeof this.endpoint.valueOf() !== 'string') {
      throw new Error('this.endpoint cannot be null or undefined and it must be of type string.');
    }
    if (mode) {
      let allowedValues = [ 'Handwritten', 'Printed' ];
      if (!allowedValues.some( function(item) { return item === mode; })) {
        throw new Error(mode + ' is not a valid value. The valid values are: ' + allowedValues);
      }
    } else {
      throw new Error('mode cannot be null or undefined.');
    }
    if (url === null || url === undefined || typeof url.valueOf() !== 'string') {
      throw new Error('url cannot be null or undefined and it must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  let imageUrl;
  if (url !== null && url !== undefined) {
    imageUrl = new client.models['ImageUrl']();
    imageUrl.url = url;
  }

  // Construct URL
  let baseUrl = this.baseUri;
  let requestUrl = baseUrl + (baseUrl.endsWith('/') ? '' : '/') + 'read/core/asyncBatchAnalyze';
  requestUrl = requestUrl.replace('{Endpoint}', this.endpoint);
  let queryParameters = [];
  queryParameters.push('mode=' + encodeURIComponent(mode));
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }

  // Create HTTP transport objects
  let httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.url = requestUrl;
  httpRequest.headers = {};
  // Set Headers
  httpRequest.headers['Content-Type'] = 'application/json; charset=utf-8';
  if(options) {
    for(let headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  // Serialize Request
  let requestContent = null;
  let requestModel = null;
  try {
    if (imageUrl !== null && imageUrl !== undefined) {
      let requestModelMapper = new client.models['ImageUrl']().mapper();
      requestModel = client.serialize(requestModelMapper, imageUrl, 'imageUrl');
      requestContent = JSON.stringify(requestModel);
    }
  } catch (error) {
    let serializationError = new Error(`Error "${error.message}" occurred in serializing the ` +
        `payload - ${JSON.stringify(imageUrl, null, 2)}.`);
    return callback(serializationError);
  }
  httpRequest.body = requestContent;
  // Send Request
  return client.pipeline(httpRequest, (err, response, responseBody) => {
    if (err) {
      return callback(err);
    }
    let statusCode = response.statusCode;
    if (statusCode !== 202) {
      let error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      let parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          let internalError = null;
          if (parsedErrorResponse.error) internalError = parsedErrorResponse.error;
          error.code = internalError ? internalError.code : parsedErrorResponse.code;
          error.message = internalError ? internalError.message : parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          let resultMapper = new client.models['ComputerVisionError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody ` +
                         `- "${responseBody}" for the default response.`;
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    let result = null;
    if (responseBody === '') responseBody = null;

    return callback(null, result, httpRequest, response);
  });
}

/**
 * This interface is used for getting OCR results of Read operation. The URL to
 * this interface should be retrieved from "Operation-Location" field returned
 * from Batch Read File interface.
 *
 * @param {string} operationId Id of read operation returned in the response of
 * the "Batch Read File" interface.
 *
 * @param {object} [options] Optional Parameters.
 *
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 *
 * @param {function} callback - The callback.
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object if an error did not occur.
 *                      See {@link ReadOperationResult} for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
function _getReadOperationResult(operationId, options, callback) {
   /* jshint validthis: true */
  let client = this;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  // Validate
  try {
    if (this.endpoint === null || this.endpoint === undefined || typeof this.endpoint.valueOf() !== 'string') {
      throw new Error('this.endpoint cannot be null or undefined and it must be of type string.');
    }
    if (operationId === null || operationId === undefined || typeof operationId.valueOf() !== 'string') {
      throw new Error('operationId cannot be null or undefined and it must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  let baseUrl = this.baseUri;
  let requestUrl = baseUrl + (baseUrl.endsWith('/') ? '' : '/') + 'read/operations/{operationId}';
  requestUrl = requestUrl.replace('{Endpoint}', this.endpoint);
  requestUrl = requestUrl.replace('{operationId}', encodeURIComponent(operationId));

  // Create HTTP transport objects
  let httpRequest = new WebResource();
  httpRequest.method = 'GET';
  httpRequest.url = requestUrl;
  httpRequest.headers = {};
  // Set Headers
  httpRequest.headers['Content-Type'] = 'application/json; charset=utf-8';
  if(options) {
    for(let headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  httpRequest.body = null;
  // Send Request
  return client.pipeline(httpRequest, (err, response, responseBody) => {
    if (err) {
      return callback(err);
    }
    let statusCode = response.statusCode;
    if (statusCode !== 200) {
      let error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      let parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          let internalError = null;
          if (parsedErrorResponse.error) internalError = parsedErrorResponse.error;
          error.code = internalError ? internalError.code : parsedErrorResponse.code;
          error.message = internalError ? internalError.message : parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          let resultMapper = new client.models['ComputerVisionError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody ` +
                         `- "${responseBody}" for the default response.`;
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    let result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      let parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          let resultMapper = new client.models['ReadOperationResult']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        let deserializationError = new Error(`Error ${error} occurred in deserializing the responseBody - ${responseBody}`);
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
}

/**
 * This operation extracts a rich set of visual features based on the image
 * content.
 * Two input methods are supported -- (1) Uploading an image or (2) specifying
 * an image URL. Within your request, there is an optional parameter to allow
 * you to choose which features to return. By default, image categories are
 * returned in the response.
 * A successful response will be returned in JSON. If the request failed, the
 * response will contain an error code and a message to help understand what
 * went wrong.
 *
 * @param {object} image An image stream.
 *
 * @param {object} [options] Optional Parameters.
 *
 * @param {array} [options.visualFeatures] A string indicating what visual
 * feature types to return. Multiple values should be comma-separated. Valid
 * visual feature types include: Categories - categorizes image content
 * according to a taxonomy defined in documentation. Tags - tags the image with
 * a detailed list of words related to the image content. Description -
 * describes the image content with a complete English sentence. Faces -
 * detects if faces are present. If present, generate coordinates, gender and
 * age. ImageType - detects if image is clipart or a line drawing. Color -
 * determines the accent color, dominant color, and whether an image is
 * black&white. Adult - detects if the image is pornographic in nature (depicts
 * nudity or a sex act).  Sexually suggestive content is also detected. Objects
 * - detects various objects within an image, including the approximate
 * location. The Objects argument is only available in English. Brands -
 * detects various brands within an image, including the approximate location.
 * The Brands argument is only available in English.
 *
 * @param {array} [options.details] A string indicating which domain-specific
 * details to return. Multiple values should be comma-separated. Valid visual
 * feature types include: Celebrities - identifies celebrities if detected in
 * the image, Landmarks - identifies notable landmarks in the image.
 *
 * @param {string} [options.language] The desired language for output
 * generation. If this parameter is not specified, the default value is
 * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
 * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
 * 'en', 'es', 'ja', 'pt', 'zh'
 *
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 *
 * @param {function} callback - The callback.
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object if an error did not occur.
 *                      See {@link ImageAnalysis} for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
function _analyzeImageInStream(image, options, callback) {
   /* jshint validthis: true */
  let client = this;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  let visualFeatures = (options && options.visualFeatures !== undefined) ? options.visualFeatures : undefined;
  let details = (options && options.details !== undefined) ? options.details : undefined;
  let language = (options && options.language !== undefined) ? options.language : 'en';
  // Validate
  try {
    if (this.endpoint === null || this.endpoint === undefined || typeof this.endpoint.valueOf() !== 'string') {
      throw new Error('this.endpoint cannot be null or undefined and it must be of type string.');
    }
    if (Array.isArray(visualFeatures)) {
      for (let i = 0; i < visualFeatures.length; i++) {
        if (visualFeatures[i]) {
          let allowedValues = [ 'ImageType', 'Faces', 'Adult', 'Categories', 'Color', 'Tags', 'Description', 'Objects', 'Brands' ];
          if (!allowedValues.some( function(item) { return item === visualFeatures[i]; })) {
            throw new Error(visualFeatures[i] + ' is not a valid value. The valid values are: ' + allowedValues);
          }
        }
      }
    }
    if (Array.isArray(details)) {
      for (let i1 = 0; i1 < details.length; i1++) {
        if (details[i1]) {
          let allowedValues1 = [ 'Celebrities', 'Landmarks' ];
          if (!allowedValues1.some( function(item) { return item === details[i1]; })) {
            throw new Error(details[i1] + ' is not a valid value. The valid values are: ' + allowedValues1);
          }
        }
      }
    }
    if (language !== null && language !== undefined && typeof language.valueOf() !== 'string') {
      throw new Error('language must be of type string.');
    }
    if (image === null || image === undefined) {
      throw new Error('image cannot be null or undefined and it must be of type object.');
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  let baseUrl = this.baseUri;
  let requestUrl = baseUrl + (baseUrl.endsWith('/') ? '' : '/') + 'analyze';
  requestUrl = requestUrl.replace('{Endpoint}', this.endpoint);
  let queryParameters = [];
  if (visualFeatures !== null && visualFeatures !== undefined) {
    queryParameters.push('visualFeatures=' + encodeURIComponent(visualFeatures.join(',')));
  }
  if (details !== null && details !== undefined) {
    queryParameters.push('details=' + encodeURIComponent(details.join(',')));
  }
  if (language !== null && language !== undefined) {
    queryParameters.push('language=' + encodeURIComponent(language));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }

  // Create HTTP transport objects
  let httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.url = requestUrl;
  httpRequest.headers = {};
  // Set Headers
  httpRequest.headers['Content-Type'] = 'application/octet-stream';
  if(options) {
    for(let headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  // Serialize Request
  let requestContent = image;
  httpRequest.body = requestContent;
  // Send Request
  return client.pipeline(httpRequest, (err, response, responseBody) => {
    if (err) {
      return callback(err);
    }
    let statusCode = response.statusCode;
    if (statusCode !== 200) {
      let error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      let parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          let internalError = null;
          if (parsedErrorResponse.error) internalError = parsedErrorResponse.error;
          error.code = internalError ? internalError.code : parsedErrorResponse.code;
          error.message = internalError ? internalError.message : parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          let resultMapper = new client.models['ComputerVisionError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody ` +
                         `- "${responseBody}" for the default response.`;
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    let result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      let parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          let resultMapper = new client.models['ImageAnalysis']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        let deserializationError = new Error(`Error ${error} occurred in deserializing the responseBody - ${responseBody}`);
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
}

/**
 * This operation returns a bounding box around the most important area of the
 * image.
 * A successful response will be returned in JSON. If the request failed, the
 * response contains an error code and a message to help determine what went
 * wrong.
 * Upon failure, the error code and an error message are returned. The error
 * code could be one of InvalidImageUrl, InvalidImageFormat, InvalidImageSize,
 * NotSupportedImage, FailedToProcess, Timeout, or InternalServerError.
 *
 * @param {object} image An image stream.
 *
 * @param {object} [options] Optional Parameters.
 *
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 *
 * @param {function} callback - The callback.
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object if an error did not occur.
 *                      See {@link AreaOfInterestResult} for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
function _getAreaOfInterestInStream(image, options, callback) {
   /* jshint validthis: true */
  let client = this;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  // Validate
  try {
    if (this.endpoint === null || this.endpoint === undefined || typeof this.endpoint.valueOf() !== 'string') {
      throw new Error('this.endpoint cannot be null or undefined and it must be of type string.');
    }
    if (image === null || image === undefined) {
      throw new Error('image cannot be null or undefined and it must be of type object.');
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  let baseUrl = this.baseUri;
  let requestUrl = baseUrl + (baseUrl.endsWith('/') ? '' : '/') + 'areaOfInterest';
  requestUrl = requestUrl.replace('{Endpoint}', this.endpoint);

  // Create HTTP transport objects
  let httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.url = requestUrl;
  httpRequest.headers = {};
  // Set Headers
  httpRequest.headers['Content-Type'] = 'application/octet-stream';
  if(options) {
    for(let headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  // Serialize Request
  let requestContent = image;
  httpRequest.body = requestContent;
  // Send Request
  return client.pipeline(httpRequest, (err, response, responseBody) => {
    if (err) {
      return callback(err);
    }
    let statusCode = response.statusCode;
    if (statusCode !== 200) {
      let error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      let parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          let internalError = null;
          if (parsedErrorResponse.error) internalError = parsedErrorResponse.error;
          error.code = internalError ? internalError.code : parsedErrorResponse.code;
          error.message = internalError ? internalError.message : parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          let resultMapper = new client.models['ComputerVisionError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody ` +
                         `- "${responseBody}" for the default response.`;
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    let result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      let parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          let resultMapper = new client.models['AreaOfInterestResult']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        let deserializationError = new Error(`Error ${error} occurred in deserializing the responseBody - ${responseBody}`);
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
}

/**
 * This operation generates a description of an image in human readable
 * language with complete sentences. The description is based on a collection
 * of content tags, which are also returned by the operation. More than one
 * description can be generated for each image. Descriptions are ordered by
 * their confidence score. All descriptions are in English.
 * Two input methods are supported -- (1) Uploading an image or (2) specifying
 * an image URL.
 * A successful response will be returned in JSON. If the request failed, the
 * response will contain an error code and a message to help understand what
 * went wrong.
 *
 * @param {object} image An image stream.
 *
 * @param {object} [options] Optional Parameters.
 *
 * @param {number} [options.maxCandidates] Maximum number of candidate
 * descriptions to be returned.  The default is 1.
 *
 * @param {string} [options.language] The desired language for output
 * generation. If this parameter is not specified, the default value is
 * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
 * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
 * 'en', 'es', 'ja', 'pt', 'zh'
 *
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 *
 * @param {function} callback - The callback.
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object if an error did not occur.
 *                      See {@link ImageDescription} for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
function _describeImageInStream(image, options, callback) {
   /* jshint validthis: true */
  let client = this;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  let maxCandidates = (options && options.maxCandidates !== undefined) ? options.maxCandidates : 1;
  let language = (options && options.language !== undefined) ? options.language : 'en';
  // Validate
  try {
    if (this.endpoint === null || this.endpoint === undefined || typeof this.endpoint.valueOf() !== 'string') {
      throw new Error('this.endpoint cannot be null or undefined and it must be of type string.');
    }
    if (maxCandidates !== null && maxCandidates !== undefined && typeof maxCandidates !== 'number') {
      throw new Error('maxCandidates must be of type number.');
    }
    if (language !== null && language !== undefined && typeof language.valueOf() !== 'string') {
      throw new Error('language must be of type string.');
    }
    if (image === null || image === undefined) {
      throw new Error('image cannot be null or undefined and it must be of type object.');
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  let baseUrl = this.baseUri;
  let requestUrl = baseUrl + (baseUrl.endsWith('/') ? '' : '/') + 'describe';
  requestUrl = requestUrl.replace('{Endpoint}', this.endpoint);
  let queryParameters = [];
  if (maxCandidates !== null && maxCandidates !== undefined) {
    queryParameters.push('maxCandidates=' + encodeURIComponent(maxCandidates.toString()));
  }
  if (language !== null && language !== undefined) {
    queryParameters.push('language=' + encodeURIComponent(language));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }

  // Create HTTP transport objects
  let httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.url = requestUrl;
  httpRequest.headers = {};
  // Set Headers
  httpRequest.headers['Content-Type'] = 'application/octet-stream';
  if(options) {
    for(let headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  // Serialize Request
  let requestContent = image;
  httpRequest.body = requestContent;
  // Send Request
  return client.pipeline(httpRequest, (err, response, responseBody) => {
    if (err) {
      return callback(err);
    }
    let statusCode = response.statusCode;
    if (statusCode !== 200) {
      let error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      let parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          let internalError = null;
          if (parsedErrorResponse.error) internalError = parsedErrorResponse.error;
          error.code = internalError ? internalError.code : parsedErrorResponse.code;
          error.message = internalError ? internalError.message : parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          let resultMapper = new client.models['ComputerVisionError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody ` +
                         `- "${responseBody}" for the default response.`;
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    let result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      let parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          let resultMapper = new client.models['ImageDescription']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        let deserializationError = new Error(`Error ${error} occurred in deserializing the responseBody - ${responseBody}`);
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
}

/**
 * Performs object detection on the specified image.
 * Two input methods are supported -- (1) Uploading an image or (2) specifying
 * an image URL.
 * A successful response will be returned in JSON. If the request failed, the
 * response will contain an error code and a message to help understand what
 * went wrong.
 *
 * @param {object} image An image stream.
 *
 * @param {object} [options] Optional Parameters.
 *
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 *
 * @param {function} callback - The callback.
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object if an error did not occur.
 *                      See {@link DetectResult} for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
function _detectObjectsInStream(image, options, callback) {
   /* jshint validthis: true */
  let client = this;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  // Validate
  try {
    if (this.endpoint === null || this.endpoint === undefined || typeof this.endpoint.valueOf() !== 'string') {
      throw new Error('this.endpoint cannot be null or undefined and it must be of type string.');
    }
    if (image === null || image === undefined) {
      throw new Error('image cannot be null or undefined and it must be of type object.');
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  let baseUrl = this.baseUri;
  let requestUrl = baseUrl + (baseUrl.endsWith('/') ? '' : '/') + 'detect';
  requestUrl = requestUrl.replace('{Endpoint}', this.endpoint);

  // Create HTTP transport objects
  let httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.url = requestUrl;
  httpRequest.headers = {};
  // Set Headers
  httpRequest.headers['Content-Type'] = 'application/octet-stream';
  if(options) {
    for(let headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  // Serialize Request
  let requestContent = image;
  httpRequest.body = requestContent;
  // Send Request
  return client.pipeline(httpRequest, (err, response, responseBody) => {
    if (err) {
      return callback(err);
    }
    let statusCode = response.statusCode;
    if (statusCode !== 200) {
      let error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      let parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          let internalError = null;
          if (parsedErrorResponse.error) internalError = parsedErrorResponse.error;
          error.code = internalError ? internalError.code : parsedErrorResponse.code;
          error.message = internalError ? internalError.message : parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          let resultMapper = new client.models['ComputerVisionError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody ` +
                         `- "${responseBody}" for the default response.`;
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    let result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      let parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          let resultMapper = new client.models['DetectResult']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        let deserializationError = new Error(`Error ${error} occurred in deserializing the responseBody - ${responseBody}`);
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
}

/**
 * This operation generates a thumbnail image with the user-specified width and
 * height. By default, the service analyzes the image, identifies the region of
 * interest (ROI), and generates smart cropping coordinates based on the ROI.
 * Smart cropping helps when you specify an aspect ratio that differs from that
 * of the input image.
 * A successful response contains the thumbnail image binary. If the request
 * failed, the response contains an error code and a message to help determine
 * what went wrong.
 * Upon failure, the error code and an error message are returned. The error
 * code could be one of InvalidImageUrl, InvalidImageFormat, InvalidImageSize,
 * InvalidThumbnailSize, NotSupportedImage, FailedToProcess, Timeout, or
 * InternalServerError.
 *
 * @param {number} width Width of the thumbnail, in pixels. It must be between
 * 1 and 1024. Recommended minimum of 50.
 *
 * @param {number} height Height of the thumbnail, in pixels. It must be
 * between 1 and 1024. Recommended minimum of 50.
 *
 * @param {object} image An image stream.
 *
 * @param {object} [options] Optional Parameters.
 *
 * @param {boolean} [options.smartCropping] Boolean flag for enabling smart
 * cropping.
 *
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 *
 * @param {function} callback - The callback.
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object if an error did not occur.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
function _generateThumbnailInStream(width, height, image, options, callback) {
   /* jshint validthis: true */
  let client = this;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  let smartCropping = (options && options.smartCropping !== undefined) ? options.smartCropping : false;
  // Validate
  try {
    if (this.endpoint === null || this.endpoint === undefined || typeof this.endpoint.valueOf() !== 'string') {
      throw new Error('this.endpoint cannot be null or undefined and it must be of type string.');
    }
    if (width === null || width === undefined || typeof width !== 'number') {
      throw new Error('width cannot be null or undefined and it must be of type number.');
    }
    if (width !== null && width !== undefined) {
      if (width > 1024)
      {
        throw new Error('"width" should satisfy the constraint - "InclusiveMaximum": 1024');
      }
      if (width < 1)
      {
        throw new Error('"width" should satisfy the constraint - "InclusiveMinimum": 1');
      }
    }
    if (height === null || height === undefined || typeof height !== 'number') {
      throw new Error('height cannot be null or undefined and it must be of type number.');
    }
    if (height !== null && height !== undefined) {
      if (height > 1024)
      {
        throw new Error('"height" should satisfy the constraint - "InclusiveMaximum": 1024');
      }
      if (height < 1)
      {
        throw new Error('"height" should satisfy the constraint - "InclusiveMinimum": 1');
      }
    }
    if (smartCropping !== null && smartCropping !== undefined && typeof smartCropping !== 'boolean') {
      throw new Error('smartCropping must be of type boolean.');
    }
    if (image === null || image === undefined) {
      throw new Error('image cannot be null or undefined and it must be of type object.');
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  let baseUrl = this.baseUri;
  let requestUrl = baseUrl + (baseUrl.endsWith('/') ? '' : '/') + 'generateThumbnail';
  requestUrl = requestUrl.replace('{Endpoint}', this.endpoint);
  let queryParameters = [];
  queryParameters.push('width=' + encodeURIComponent(width.toString()));
  queryParameters.push('height=' + encodeURIComponent(height.toString()));
  if (smartCropping !== null && smartCropping !== undefined) {
    queryParameters.push('smartCropping=' + encodeURIComponent(smartCropping.toString()));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }

  // Create HTTP transport objects
  let httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.url = requestUrl;
  httpRequest.headers = {};
  // Set Headers
  httpRequest.headers['Content-Type'] = 'application/octet-stream';
  if(options) {
    for(let headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  // Serialize Request
  let requestContent = image;
  httpRequest.body = requestContent;
  // Send Request
  httpRequest.streamedResponse = true;
  return client.pipeline(httpRequest, (err, response, responseBody) => {
    if (err) {
      return callback(err);
    }

    let statusCode = response.statusCode;
    if (statusCode !== 200) {
      let error = new Error(`Unexpected status code: ${statusCode}`);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      let parsedErrorResponse;
      try {
        if (responseBody !== undefined) parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          let internalError = null;
          if (parsedErrorResponse.error) internalError = parsedErrorResponse.error;
          error.code = internalError ? internalError.code : parsedErrorResponse.code;
          error.message = internalError ? internalError.message : parsedErrorResponse.message;
        }
      } catch (defaultError) {
        error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody ` +
                         `- "${responseBody}" for the default response.`;
        return callback(error);
      }
      return callback(error);
    }

    // Create Result
    let result = response;
    return callback(null, result, httpRequest, response);
  });
}

/**
 * This operation recognizes content within an image by applying a
 * domain-specific model. The list of domain-specific models that are supported
 * by the Computer Vision API can be retrieved using the /models GET request.
 * Currently, the API provides following domain-specific models: celebrities,
 * landmarks.
 * Two input methods are supported -- (1) Uploading an image or (2) specifying
 * an image URL.
 * A successful response will be returned in JSON.
 * If the request failed, the response will contain an error code and a message
 * to help understand what went wrong.
 *
 * @param {string} model The domain-specific content to recognize.
 *
 * @param {object} image An image stream.
 *
 * @param {object} [options] Optional Parameters.
 *
 * @param {string} [options.language] The desired language for output
 * generation. If this parameter is not specified, the default value is
 * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
 * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
 * 'en', 'es', 'ja', 'pt', 'zh'
 *
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 *
 * @param {function} callback - The callback.
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object if an error did not occur.
 *                      See {@link DomainModelResults} for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
function _analyzeImageByDomainInStream(model, image, options, callback) {
   /* jshint validthis: true */
  let client = this;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  let language = (options && options.language !== undefined) ? options.language : 'en';
  // Validate
  try {
    if (this.endpoint === null || this.endpoint === undefined || typeof this.endpoint.valueOf() !== 'string') {
      throw new Error('this.endpoint cannot be null or undefined and it must be of type string.');
    }
    if (model === null || model === undefined || typeof model.valueOf() !== 'string') {
      throw new Error('model cannot be null or undefined and it must be of type string.');
    }
    if (language !== null && language !== undefined && typeof language.valueOf() !== 'string') {
      throw new Error('language must be of type string.');
    }
    if (image === null || image === undefined) {
      throw new Error('image cannot be null or undefined and it must be of type object.');
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  let baseUrl = this.baseUri;
  let requestUrl = baseUrl + (baseUrl.endsWith('/') ? '' : '/') + 'models/{model}/analyze';
  requestUrl = requestUrl.replace('{Endpoint}', this.endpoint);
  requestUrl = requestUrl.replace('{model}', encodeURIComponent(model));
  let queryParameters = [];
  if (language !== null && language !== undefined) {
    queryParameters.push('language=' + encodeURIComponent(language));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }

  // Create HTTP transport objects
  let httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.url = requestUrl;
  httpRequest.headers = {};
  // Set Headers
  httpRequest.headers['Content-Type'] = 'application/octet-stream';
  if(options) {
    for(let headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  // Serialize Request
  let requestContent = image;
  httpRequest.body = requestContent;
  // Send Request
  return client.pipeline(httpRequest, (err, response, responseBody) => {
    if (err) {
      return callback(err);
    }
    let statusCode = response.statusCode;
    if (statusCode !== 200) {
      let error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      let parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          let internalError = null;
          if (parsedErrorResponse.error) internalError = parsedErrorResponse.error;
          error.code = internalError ? internalError.code : parsedErrorResponse.code;
          error.message = internalError ? internalError.message : parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          let resultMapper = new client.models['ComputerVisionError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody ` +
                         `- "${responseBody}" for the default response.`;
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    let result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      let parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          let resultMapper = new client.models['DomainModelResults']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        let deserializationError = new Error(`Error ${error} occurred in deserializing the responseBody - ${responseBody}`);
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
}

/**
 * Optical Character Recognition (OCR) detects text in an image and extracts
 * the recognized characters into a machine-usable character stream.
 * Upon success, the OCR results will be returned.
 * Upon failure, the error code together with an error message will be
 * returned. The error code can be one of InvalidImageUrl, InvalidImageFormat,
 * InvalidImageSize, NotSupportedImage, NotSupportedLanguage, or
 * InternalServerError.
 *
 * @param {boolean} detectOrientation Whether detect the text orientation in
 * the image. With detectOrientation=true the OCR service tries to detect the
 * image orientation and correct it before further processing (e.g. if it's
 * upside-down).
 *
 * @param {object} image An image stream.
 *
 * @param {object} [options] Optional Parameters.
 *
 * @param {string} [options.language] The BCP-47 language code of the text to
 * be detected in the image. The default value is 'unk'. Possible values
 * include: 'unk', 'zh-Hans', 'zh-Hant', 'cs', 'da', 'nl', 'en', 'fi', 'fr',
 * 'de', 'el', 'hu', 'it', 'ja', 'ko', 'nb', 'pl', 'pt', 'ru', 'es', 'sv',
 * 'tr', 'ar', 'ro', 'sr-Cyrl', 'sr-Latn', 'sk'
 *
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 *
 * @param {function} callback - The callback.
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object if an error did not occur.
 *                      See {@link OcrResult} for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
function _recognizePrintedTextInStream(detectOrientation, image, options, callback) {
   /* jshint validthis: true */
  let client = this;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  let language = (options && options.language !== undefined) ? options.language : 'unk';
  // Validate
  try {
    if (this.endpoint === null || this.endpoint === undefined || typeof this.endpoint.valueOf() !== 'string') {
      throw new Error('this.endpoint cannot be null or undefined and it must be of type string.');
    }
    if (detectOrientation === null || detectOrientation === undefined || typeof detectOrientation !== 'boolean') {
      throw new Error('detectOrientation cannot be null or undefined and it must be of type boolean.');
    }
    if (language) {
      let allowedValues = [ 'unk', 'zh-Hans', 'zh-Hant', 'cs', 'da', 'nl', 'en', 'fi', 'fr', 'de', 'el', 'hu', 'it', 'ja', 'ko', 'nb', 'pl', 'pt', 'ru', 'es', 'sv', 'tr', 'ar', 'ro', 'sr-Cyrl', 'sr-Latn', 'sk' ];
      if (!allowedValues.some( function(item) { return item === language; })) {
        throw new Error(language + ' is not a valid value. The valid values are: ' + allowedValues);
      }
    }
    if (image === null || image === undefined) {
      throw new Error('image cannot be null or undefined and it must be of type object.');
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  let baseUrl = this.baseUri;
  let requestUrl = baseUrl + (baseUrl.endsWith('/') ? '' : '/') + 'ocr';
  requestUrl = requestUrl.replace('{Endpoint}', this.endpoint);
  let queryParameters = [];
  queryParameters.push('detectOrientation=' + encodeURIComponent(detectOrientation.toString()));
  if (language !== null && language !== undefined) {
    queryParameters.push('language=' + encodeURIComponent(language));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }

  // Create HTTP transport objects
  let httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.url = requestUrl;
  httpRequest.headers = {};
  // Set Headers
  httpRequest.headers['Content-Type'] = 'application/octet-stream';
  if(options) {
    for(let headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  // Serialize Request
  let requestContent = image;
  httpRequest.body = requestContent;
  // Send Request
  return client.pipeline(httpRequest, (err, response, responseBody) => {
    if (err) {
      return callback(err);
    }
    let statusCode = response.statusCode;
    if (statusCode !== 200) {
      let error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      let parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          let internalError = null;
          if (parsedErrorResponse.error) internalError = parsedErrorResponse.error;
          error.code = internalError ? internalError.code : parsedErrorResponse.code;
          error.message = internalError ? internalError.message : parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          let resultMapper = new client.models['ComputerVisionError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody ` +
                         `- "${responseBody}" for the default response.`;
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    let result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      let parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          let resultMapper = new client.models['OcrResult']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        let deserializationError = new Error(`Error ${error} occurred in deserializing the responseBody - ${responseBody}`);
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
}

/**
 * This operation generates a list of words, or tags, that are relevant to the
 * content of the supplied image. The Computer Vision API can return tags based
 * on objects, living beings, scenery or actions found in images. Unlike
 * categories, tags are not organized according to a hierarchical
 * classification system, but correspond to image content. Tags may contain
 * hints to avoid ambiguity or provide context, for example the tag "cello" may
 * be accompanied by the hint "musical instrument". All tags are in English.
 * Two input methods are supported -- (1) Uploading an image or (2) specifying
 * an image URL.
 * A successful response will be returned in JSON. If the request failed, the
 * response will contain an error code and a message to help understand what
 * went wrong.
 *
 * @param {object} image An image stream.
 *
 * @param {object} [options] Optional Parameters.
 *
 * @param {string} [options.language] The desired language for output
 * generation. If this parameter is not specified, the default value is
 * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
 * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
 * 'en', 'es', 'ja', 'pt', 'zh'
 *
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 *
 * @param {function} callback - The callback.
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object if an error did not occur.
 *                      See {@link TagResult} for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
function _tagImageInStream(image, options, callback) {
   /* jshint validthis: true */
  let client = this;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  let language = (options && options.language !== undefined) ? options.language : 'en';
  // Validate
  try {
    if (this.endpoint === null || this.endpoint === undefined || typeof this.endpoint.valueOf() !== 'string') {
      throw new Error('this.endpoint cannot be null or undefined and it must be of type string.');
    }
    if (language !== null && language !== undefined && typeof language.valueOf() !== 'string') {
      throw new Error('language must be of type string.');
    }
    if (image === null || image === undefined) {
      throw new Error('image cannot be null or undefined and it must be of type object.');
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  let baseUrl = this.baseUri;
  let requestUrl = baseUrl + (baseUrl.endsWith('/') ? '' : '/') + 'tag';
  requestUrl = requestUrl.replace('{Endpoint}', this.endpoint);
  let queryParameters = [];
  if (language !== null && language !== undefined) {
    queryParameters.push('language=' + encodeURIComponent(language));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }

  // Create HTTP transport objects
  let httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.url = requestUrl;
  httpRequest.headers = {};
  // Set Headers
  httpRequest.headers['Content-Type'] = 'application/octet-stream';
  if(options) {
    for(let headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  // Serialize Request
  let requestContent = image;
  httpRequest.body = requestContent;
  // Send Request
  return client.pipeline(httpRequest, (err, response, responseBody) => {
    if (err) {
      return callback(err);
    }
    let statusCode = response.statusCode;
    if (statusCode !== 200) {
      let error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      let parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          let internalError = null;
          if (parsedErrorResponse.error) internalError = parsedErrorResponse.error;
          error.code = internalError ? internalError.code : parsedErrorResponse.code;
          error.message = internalError ? internalError.message : parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          let resultMapper = new client.models['ComputerVisionError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody ` +
                         `- "${responseBody}" for the default response.`;
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    let result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      let parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          let resultMapper = new client.models['TagResult']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        let deserializationError = new Error(`Error ${error} occurred in deserializing the responseBody - ${responseBody}`);
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
}

/**
 * Recognize Text operation. When you use the Recognize Text interface, the
 * response contains a field called 'Operation-Location'. The
 * 'Operation-Location' field contains the URL that you must use for your Get
 * Recognize Text Operation Result operation.
 *
 * @param {object} image An image stream.
 *
 * @param {string} mode Type of text to recognize. Possible values include:
 * 'Handwritten', 'Printed'
 *
 * @param {object} [options] Optional Parameters.
 *
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 *
 * @param {function} callback - The callback.
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {null} [result]   - The deserialized result object if an error did not occur.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
function _recognizeTextInStream(image, mode, options, callback) {
   /* jshint validthis: true */
  let client = this;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  // Validate
  try {
    if (this.endpoint === null || this.endpoint === undefined || typeof this.endpoint.valueOf() !== 'string') {
      throw new Error('this.endpoint cannot be null or undefined and it must be of type string.');
    }
    if (image === null || image === undefined) {
      throw new Error('image cannot be null or undefined and it must be of type object.');
    }
    if (mode) {
      let allowedValues = [ 'Handwritten', 'Printed' ];
      if (!allowedValues.some( function(item) { return item === mode; })) {
        throw new Error(mode + ' is not a valid value. The valid values are: ' + allowedValues);
      }
    } else {
      throw new Error('mode cannot be null or undefined.');
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  let baseUrl = this.baseUri;
  let requestUrl = baseUrl + (baseUrl.endsWith('/') ? '' : '/') + 'recognizeText';
  requestUrl = requestUrl.replace('{Endpoint}', this.endpoint);
  let queryParameters = [];
  queryParameters.push('mode=' + encodeURIComponent(mode));
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }

  // Create HTTP transport objects
  let httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.url = requestUrl;
  httpRequest.headers = {};
  // Set Headers
  httpRequest.headers['Content-Type'] = 'application/octet-stream';
  if(options) {
    for(let headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  // Serialize Request
  let requestContent = image;
  httpRequest.body = requestContent;
  // Send Request
  return client.pipeline(httpRequest, (err, response, responseBody) => {
    if (err) {
      return callback(err);
    }
    let statusCode = response.statusCode;
    if (statusCode !== 202) {
      let error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      let parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          let internalError = null;
          if (parsedErrorResponse.error) internalError = parsedErrorResponse.error;
          error.code = internalError ? internalError.code : parsedErrorResponse.code;
          error.message = internalError ? internalError.message : parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          let resultMapper = new client.models['ComputerVisionError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody ` +
                         `- "${responseBody}" for the default response.`;
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    let result = null;
    if (responseBody === '') responseBody = null;

    return callback(null, result, httpRequest, response);
  });
}

/**
 * Use this interface to get the result of a Read Document operation, employing
 * the state-of-the-art Optical Character Recognition (OCR) algorithms
 * optimized for text-heavy documents. When you use the Read Document
 * interface, the response contains a field called "Operation-Location". The
 * "Operation-Location" field contains the URL that you must use for your "Get
 * Read Result operation" to access OCR results.​
 *
 * @param {object} image An image stream.
 *
 * @param {string} mode Type of text to recognize. Possible values include:
 * 'Handwritten', 'Printed'
 *
 * @param {object} [options] Optional Parameters.
 *
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 *
 * @param {function} callback - The callback.
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {null} [result]   - The deserialized result object if an error did not occur.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
function _batchReadFileInStream(image, mode, options, callback) {
   /* jshint validthis: true */
  let client = this;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  // Validate
  try {
    if (this.endpoint === null || this.endpoint === undefined || typeof this.endpoint.valueOf() !== 'string') {
      throw new Error('this.endpoint cannot be null or undefined and it must be of type string.');
    }
    if (image === null || image === undefined) {
      throw new Error('image cannot be null or undefined and it must be of type object.');
    }
    if (mode) {
      let allowedValues = [ 'Handwritten', 'Printed' ];
      if (!allowedValues.some( function(item) { return item === mode; })) {
        throw new Error(mode + ' is not a valid value. The valid values are: ' + allowedValues);
      }
    } else {
      throw new Error('mode cannot be null or undefined.');
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  let baseUrl = this.baseUri;
  let requestUrl = baseUrl + (baseUrl.endsWith('/') ? '' : '/') + 'read/core/asyncBatchAnalyze';
  requestUrl = requestUrl.replace('{Endpoint}', this.endpoint);
  let queryParameters = [];
  queryParameters.push('mode=' + encodeURIComponent(mode));
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }

  // Create HTTP transport objects
  let httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.url = requestUrl;
  httpRequest.headers = {};
  // Set Headers
  httpRequest.headers['Content-Type'] = 'application/octet-stream';
  if(options) {
    for(let headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  // Serialize Request
  let requestContent = image;
  httpRequest.body = requestContent;
  // Send Request
  return client.pipeline(httpRequest, (err, response, responseBody) => {
    if (err) {
      return callback(err);
    }
    let statusCode = response.statusCode;
    if (statusCode !== 202) {
      let error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      let parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          let internalError = null;
          if (parsedErrorResponse.error) internalError = parsedErrorResponse.error;
          error.code = internalError ? internalError.code : parsedErrorResponse.code;
          error.message = internalError ? internalError.message : parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          let resultMapper = new client.models['ComputerVisionError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody ` +
                         `- "${responseBody}" for the default response.`;
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    let result = null;
    if (responseBody === '') responseBody = null;

    return callback(null, result, httpRequest, response);
  });
}

/** Class representing a ComputerVisionClient. */
class ComputerVisionClient extends ServiceClient {
  /**
   * Create a ComputerVisionClient.
   * @param {credentials} credentials - Subscription credentials which uniquely identify client subscription.
   * @param {string} endpoint - Supported Cognitive Services endpoints.
   * @param {object} [options] - The parameter options
   * @param {Array} [options.filters] - Filters to be added to the request pipeline
   * @param {object} [options.requestOptions] - Options for the underlying request object
   * {@link https://github.com/request/request#requestoptions-callback Options doc}
   * @param {boolean} [options.noRetryPolicy] - If set to true, turn off default retry policy
   */
  constructor(credentials, endpoint, options) {
    if (credentials === null || credentials === undefined) {
      throw new Error('\'credentials\' cannot be null.');
    }
    if (endpoint === null || endpoint === undefined) {
      throw new Error('\'endpoint\' cannot be null.');
    }

    if (!options) options = {};

    super(credentials, options);

    this.baseUri = '{Endpoint}/vision/v2.0';
    this.credentials = credentials;
    this.endpoint = endpoint;

    let packageInfo = this.getPackageJsonInfo(__dirname);
    this.addUserAgentInfo(`${packageInfo.name}/${packageInfo.version}`);
    this.models = models;
    this._analyzeImage = _analyzeImage;
    this._describeImage = _describeImage;
    this._detectObjects = _detectObjects;
    this._listModels = _listModels;
    this._analyzeImageByDomain = _analyzeImageByDomain;
    this._recognizePrintedText = _recognizePrintedText;
    this._tagImage = _tagImage;
    this._generateThumbnail = _generateThumbnail;
    this._getAreaOfInterest = _getAreaOfInterest;
    this._recognizeText = _recognizeText;
    this._getTextOperationResult = _getTextOperationResult;
    this._batchReadFile = _batchReadFile;
    this._getReadOperationResult = _getReadOperationResult;
    this._analyzeImageInStream = _analyzeImageInStream;
    this._getAreaOfInterestInStream = _getAreaOfInterestInStream;
    this._describeImageInStream = _describeImageInStream;
    this._detectObjectsInStream = _detectObjectsInStream;
    this._generateThumbnailInStream = _generateThumbnailInStream;
    this._analyzeImageByDomainInStream = _analyzeImageByDomainInStream;
    this._recognizePrintedTextInStream = _recognizePrintedTextInStream;
    this._tagImageInStream = _tagImageInStream;
    this._recognizeTextInStream = _recognizeTextInStream;
    this._batchReadFileInStream = _batchReadFileInStream;
    msRest.addSerializationMixin(this);
  }

  /**
   * This operation extracts a rich set of visual features based on the image
   * content.
   * Two input methods are supported -- (1) Uploading an image or (2) specifying
   * an image URL. Within your request, there is an optional parameter to allow
   * you to choose which features to return. By default, image categories are
   * returned in the response.
   * A successful response will be returned in JSON. If the request failed, the
   * response will contain an error code and a message to help understand what
   * went wrong.
   *
   * @param {string} url Publicly reachable URL of an image.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {array} [options.visualFeatures] A string indicating what visual
   * feature types to return. Multiple values should be comma-separated. Valid
   * visual feature types include: Categories - categorizes image content
   * according to a taxonomy defined in documentation. Tags - tags the image with
   * a detailed list of words related to the image content. Description -
   * describes the image content with a complete English sentence. Faces -
   * detects if faces are present. If present, generate coordinates, gender and
   * age. ImageType - detects if image is clipart or a line drawing. Color -
   * determines the accent color, dominant color, and whether an image is
   * black&white. Adult - detects if the image is pornographic in nature (depicts
   * nudity or a sex act).  Sexually suggestive content is also detected. Objects
   * - detects various objects within an image, including the approximate
   * location. The Objects argument is only available in English. Brands -
   * detects various brands within an image, including the approximate location.
   * The Brands argument is only available in English.
   *
   * @param {array} [options.details] A string indicating which domain-specific
   * details to return. Multiple values should be comma-separated. Valid visual
   * feature types include: Celebrities - identifies celebrities if detected in
   * the image, Landmarks - identifies notable landmarks in the image.
   *
   * @param {string} [options.language] The desired language for output
   * generation. If this parameter is not specified, the default value is
   * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
   * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
   * 'en', 'es', 'ja', 'pt', 'zh'
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @returns {Promise} A promise is returned
   *
   * @resolve {HttpOperationResponse<ImageAnalysis>} - The deserialized result object.
   *
   * @reject {Error} - The error object.
   */
  analyzeImageWithHttpOperationResponse(url, options) {
    let client = this;
    let self = this;
    return new Promise((resolve, reject) => {
      self._analyzeImage(url, options, (err, result, request, response) => {
        let httpOperationResponse = new msRest.HttpOperationResponse(request, response);
        httpOperationResponse.body = result;
        if (err) { reject(err); }
        else { resolve(httpOperationResponse); }
        return;
      });
    });
  }

  /**
   * This operation extracts a rich set of visual features based on the image
   * content.
   * Two input methods are supported -- (1) Uploading an image or (2) specifying
   * an image URL. Within your request, there is an optional parameter to allow
   * you to choose which features to return. By default, image categories are
   * returned in the response.
   * A successful response will be returned in JSON. If the request failed, the
   * response will contain an error code and a message to help understand what
   * went wrong.
   *
   * @param {string} url Publicly reachable URL of an image.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {array} [options.visualFeatures] A string indicating what visual
   * feature types to return. Multiple values should be comma-separated. Valid
   * visual feature types include: Categories - categorizes image content
   * according to a taxonomy defined in documentation. Tags - tags the image with
   * a detailed list of words related to the image content. Description -
   * describes the image content with a complete English sentence. Faces -
   * detects if faces are present. If present, generate coordinates, gender and
   * age. ImageType - detects if image is clipart or a line drawing. Color -
   * determines the accent color, dominant color, and whether an image is
   * black&white. Adult - detects if the image is pornographic in nature (depicts
   * nudity or a sex act).  Sexually suggestive content is also detected. Objects
   * - detects various objects within an image, including the approximate
   * location. The Objects argument is only available in English. Brands -
   * detects various brands within an image, including the approximate location.
   * The Brands argument is only available in English.
   *
   * @param {array} [options.details] A string indicating which domain-specific
   * details to return. Multiple values should be comma-separated. Valid visual
   * feature types include: Celebrities - identifies celebrities if detected in
   * the image, Landmarks - identifies notable landmarks in the image.
   *
   * @param {string} [options.language] The desired language for output
   * generation. If this parameter is not specified, the default value is
   * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
   * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
   * 'en', 'es', 'ja', 'pt', 'zh'
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @param {function} [optionalCallback] - The optional callback.
   *
   * @returns {function|Promise} If a callback was passed as the last parameter
   * then it returns the callback else returns a Promise.
   *
   * {Promise} A promise is returned
   *
   *                      @resolve {ImageAnalysis} - The deserialized result object.
   *
   *                      @reject {Error} - The error object.
   *
   * {function} optionalCallback(err, result, request, response)
   *
   *                      {Error}  err        - The Error object if an error occurred, null otherwise.
   *
   *                      {object} [result]   - The deserialized result object if an error did not occur.
   *                      See {@link ImageAnalysis} for more information.
   *
   *                      {object} [request]  - The HTTP Request object if an error did not occur.
   *
   *                      {stream} [response] - The HTTP Response stream if an error did not occur.
   */
  analyzeImage(url, options, optionalCallback) {
    let client = this;
    let self = this;
    if (!optionalCallback && typeof options === 'function') {
      optionalCallback = options;
      options = null;
    }
    if (!optionalCallback) {
      return new Promise((resolve, reject) => {
        self._analyzeImage(url, options, (err, result, request, response) => {
          if (err) { reject(err); }
          else { resolve(result); }
          return;
        });
      });
    } else {
      return self._analyzeImage(url, options, optionalCallback);
    }
  }

  /**
   * This operation generates a description of an image in human readable
   * language with complete sentences. The description is based on a collection
   * of content tags, which are also returned by the operation. More than one
   * description can be generated for each image. Descriptions are ordered by
   * their confidence score. All descriptions are in English.
   * Two input methods are supported -- (1) Uploading an image or (2) specifying
   * an image URL.
   * A successful response will be returned in JSON. If the request failed, the
   * response will contain an error code and a message to help understand what
   * went wrong.
   *
   * @param {string} url Publicly reachable URL of an image.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {number} [options.maxCandidates] Maximum number of candidate
   * descriptions to be returned.  The default is 1.
   *
   * @param {string} [options.language] The desired language for output
   * generation. If this parameter is not specified, the default value is
   * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
   * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
   * 'en', 'es', 'ja', 'pt', 'zh'
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @returns {Promise} A promise is returned
   *
   * @resolve {HttpOperationResponse<ImageDescription>} - The deserialized result object.
   *
   * @reject {Error} - The error object.
   */
  describeImageWithHttpOperationResponse(url, options) {
    let client = this;
    let self = this;
    return new Promise((resolve, reject) => {
      self._describeImage(url, options, (err, result, request, response) => {
        let httpOperationResponse = new msRest.HttpOperationResponse(request, response);
        httpOperationResponse.body = result;
        if (err) { reject(err); }
        else { resolve(httpOperationResponse); }
        return;
      });
    });
  }

  /**
   * This operation generates a description of an image in human readable
   * language with complete sentences. The description is based on a collection
   * of content tags, which are also returned by the operation. More than one
   * description can be generated for each image. Descriptions are ordered by
   * their confidence score. All descriptions are in English.
   * Two input methods are supported -- (1) Uploading an image or (2) specifying
   * an image URL.
   * A successful response will be returned in JSON. If the request failed, the
   * response will contain an error code and a message to help understand what
   * went wrong.
   *
   * @param {string} url Publicly reachable URL of an image.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {number} [options.maxCandidates] Maximum number of candidate
   * descriptions to be returned.  The default is 1.
   *
   * @param {string} [options.language] The desired language for output
   * generation. If this parameter is not specified, the default value is
   * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
   * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
   * 'en', 'es', 'ja', 'pt', 'zh'
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @param {function} [optionalCallback] - The optional callback.
   *
   * @returns {function|Promise} If a callback was passed as the last parameter
   * then it returns the callback else returns a Promise.
   *
   * {Promise} A promise is returned
   *
   *                      @resolve {ImageDescription} - The deserialized result object.
   *
   *                      @reject {Error} - The error object.
   *
   * {function} optionalCallback(err, result, request, response)
   *
   *                      {Error}  err        - The Error object if an error occurred, null otherwise.
   *
   *                      {object} [result]   - The deserialized result object if an error did not occur.
   *                      See {@link ImageDescription} for more information.
   *
   *                      {object} [request]  - The HTTP Request object if an error did not occur.
   *
   *                      {stream} [response] - The HTTP Response stream if an error did not occur.
   */
  describeImage(url, options, optionalCallback) {
    let client = this;
    let self = this;
    if (!optionalCallback && typeof options === 'function') {
      optionalCallback = options;
      options = null;
    }
    if (!optionalCallback) {
      return new Promise((resolve, reject) => {
        self._describeImage(url, options, (err, result, request, response) => {
          if (err) { reject(err); }
          else { resolve(result); }
          return;
        });
      });
    } else {
      return self._describeImage(url, options, optionalCallback);
    }
  }

  /**
   * Performs object detection on the specified image.
   * Two input methods are supported -- (1) Uploading an image or (2) specifying
   * an image URL.
   * A successful response will be returned in JSON. If the request failed, the
   * response will contain an error code and a message to help understand what
   * went wrong.
   *
   * @param {string} url Publicly reachable URL of an image.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @returns {Promise} A promise is returned
   *
   * @resolve {HttpOperationResponse<DetectResult>} - The deserialized result object.
   *
   * @reject {Error} - The error object.
   */
  detectObjectsWithHttpOperationResponse(url, options) {
    let client = this;
    let self = this;
    return new Promise((resolve, reject) => {
      self._detectObjects(url, options, (err, result, request, response) => {
        let httpOperationResponse = new msRest.HttpOperationResponse(request, response);
        httpOperationResponse.body = result;
        if (err) { reject(err); }
        else { resolve(httpOperationResponse); }
        return;
      });
    });
  }

  /**
   * Performs object detection on the specified image.
   * Two input methods are supported -- (1) Uploading an image or (2) specifying
   * an image URL.
   * A successful response will be returned in JSON. If the request failed, the
   * response will contain an error code and a message to help understand what
   * went wrong.
   *
   * @param {string} url Publicly reachable URL of an image.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @param {function} [optionalCallback] - The optional callback.
   *
   * @returns {function|Promise} If a callback was passed as the last parameter
   * then it returns the callback else returns a Promise.
   *
   * {Promise} A promise is returned
   *
   *                      @resolve {DetectResult} - The deserialized result object.
   *
   *                      @reject {Error} - The error object.
   *
   * {function} optionalCallback(err, result, request, response)
   *
   *                      {Error}  err        - The Error object if an error occurred, null otherwise.
   *
   *                      {object} [result]   - The deserialized result object if an error did not occur.
   *                      See {@link DetectResult} for more information.
   *
   *                      {object} [request]  - The HTTP Request object if an error did not occur.
   *
   *                      {stream} [response] - The HTTP Response stream if an error did not occur.
   */
  detectObjects(url, options, optionalCallback) {
    let client = this;
    let self = this;
    if (!optionalCallback && typeof options === 'function') {
      optionalCallback = options;
      options = null;
    }
    if (!optionalCallback) {
      return new Promise((resolve, reject) => {
        self._detectObjects(url, options, (err, result, request, response) => {
          if (err) { reject(err); }
          else { resolve(result); }
          return;
        });
      });
    } else {
      return self._detectObjects(url, options, optionalCallback);
    }
  }

  /**
   * This operation returns the list of domain-specific models that are supported
   * by the Computer Vision API. Currently, the API supports following
   * domain-specific models: celebrity recognizer, landmark recognizer.
   * A successful response will be returned in JSON. If the request failed, the
   * response will contain an error code and a message to help understand what
   * went wrong.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @returns {Promise} A promise is returned
   *
   * @resolve {HttpOperationResponse<ListModelsResult>} - The deserialized result object.
   *
   * @reject {Error} - The error object.
   */
  listModelsWithHttpOperationResponse(options) {
    let client = this;
    let self = this;
    return new Promise((resolve, reject) => {
      self._listModels(options, (err, result, request, response) => {
        let httpOperationResponse = new msRest.HttpOperationResponse(request, response);
        httpOperationResponse.body = result;
        if (err) { reject(err); }
        else { resolve(httpOperationResponse); }
        return;
      });
    });
  }

  /**
   * This operation returns the list of domain-specific models that are supported
   * by the Computer Vision API. Currently, the API supports following
   * domain-specific models: celebrity recognizer, landmark recognizer.
   * A successful response will be returned in JSON. If the request failed, the
   * response will contain an error code and a message to help understand what
   * went wrong.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @param {function} [optionalCallback] - The optional callback.
   *
   * @returns {function|Promise} If a callback was passed as the last parameter
   * then it returns the callback else returns a Promise.
   *
   * {Promise} A promise is returned
   *
   *                      @resolve {ListModelsResult} - The deserialized result object.
   *
   *                      @reject {Error} - The error object.
   *
   * {function} optionalCallback(err, result, request, response)
   *
   *                      {Error}  err        - The Error object if an error occurred, null otherwise.
   *
   *                      {object} [result]   - The deserialized result object if an error did not occur.
   *                      See {@link ListModelsResult} for more information.
   *
   *                      {object} [request]  - The HTTP Request object if an error did not occur.
   *
   *                      {stream} [response] - The HTTP Response stream if an error did not occur.
   */
  listModels(options, optionalCallback) {
    let client = this;
    let self = this;
    if (!optionalCallback && typeof options === 'function') {
      optionalCallback = options;
      options = null;
    }
    if (!optionalCallback) {
      return new Promise((resolve, reject) => {
        self._listModels(options, (err, result, request, response) => {
          if (err) { reject(err); }
          else { resolve(result); }
          return;
        });
      });
    } else {
      return self._listModels(options, optionalCallback);
    }
  }

  /**
   * This operation recognizes content within an image by applying a
   * domain-specific model. The list of domain-specific models that are supported
   * by the Computer Vision API can be retrieved using the /models GET request.
   * Currently, the API provides following domain-specific models: celebrities,
   * landmarks.
   * Two input methods are supported -- (1) Uploading an image or (2) specifying
   * an image URL.
   * A successful response will be returned in JSON.
   * If the request failed, the response will contain an error code and a message
   * to help understand what went wrong.
   *
   * @param {string} model The domain-specific content to recognize.
   *
   * @param {string} url Publicly reachable URL of an image.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {string} [options.language] The desired language for output
   * generation. If this parameter is not specified, the default value is
   * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
   * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
   * 'en', 'es', 'ja', 'pt', 'zh'
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @returns {Promise} A promise is returned
   *
   * @resolve {HttpOperationResponse<DomainModelResults>} - The deserialized result object.
   *
   * @reject {Error} - The error object.
   */
  analyzeImageByDomainWithHttpOperationResponse(model, url, options) {
    let client = this;
    let self = this;
    return new Promise((resolve, reject) => {
      self._analyzeImageByDomain(model, url, options, (err, result, request, response) => {
        let httpOperationResponse = new msRest.HttpOperationResponse(request, response);
        httpOperationResponse.body = result;
        if (err) { reject(err); }
        else { resolve(httpOperationResponse); }
        return;
      });
    });
  }

  /**
   * This operation recognizes content within an image by applying a
   * domain-specific model. The list of domain-specific models that are supported
   * by the Computer Vision API can be retrieved using the /models GET request.
   * Currently, the API provides following domain-specific models: celebrities,
   * landmarks.
   * Two input methods are supported -- (1) Uploading an image or (2) specifying
   * an image URL.
   * A successful response will be returned in JSON.
   * If the request failed, the response will contain an error code and a message
   * to help understand what went wrong.
   *
   * @param {string} model The domain-specific content to recognize.
   *
   * @param {string} url Publicly reachable URL of an image.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {string} [options.language] The desired language for output
   * generation. If this parameter is not specified, the default value is
   * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
   * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
   * 'en', 'es', 'ja', 'pt', 'zh'
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @param {function} [optionalCallback] - The optional callback.
   *
   * @returns {function|Promise} If a callback was passed as the last parameter
   * then it returns the callback else returns a Promise.
   *
   * {Promise} A promise is returned
   *
   *                      @resolve {DomainModelResults} - The deserialized result object.
   *
   *                      @reject {Error} - The error object.
   *
   * {function} optionalCallback(err, result, request, response)
   *
   *                      {Error}  err        - The Error object if an error occurred, null otherwise.
   *
   *                      {object} [result]   - The deserialized result object if an error did not occur.
   *                      See {@link DomainModelResults} for more information.
   *
   *                      {object} [request]  - The HTTP Request object if an error did not occur.
   *
   *                      {stream} [response] - The HTTP Response stream if an error did not occur.
   */
  analyzeImageByDomain(model, url, options, optionalCallback) {
    let client = this;
    let self = this;
    if (!optionalCallback && typeof options === 'function') {
      optionalCallback = options;
      options = null;
    }
    if (!optionalCallback) {
      return new Promise((resolve, reject) => {
        self._analyzeImageByDomain(model, url, options, (err, result, request, response) => {
          if (err) { reject(err); }
          else { resolve(result); }
          return;
        });
      });
    } else {
      return self._analyzeImageByDomain(model, url, options, optionalCallback);
    }
  }

  /**
   * Optical Character Recognition (OCR) detects text in an image and extracts
   * the recognized characters into a machine-usable character stream.
   * Upon success, the OCR results will be returned.
   * Upon failure, the error code together with an error message will be
   * returned. The error code can be one of InvalidImageUrl, InvalidImageFormat,
   * InvalidImageSize, NotSupportedImage, NotSupportedLanguage, or
   * InternalServerError.
   *
   * @param {boolean} detectOrientation Whether detect the text orientation in
   * the image. With detectOrientation=true the OCR service tries to detect the
   * image orientation and correct it before further processing (e.g. if it's
   * upside-down).
   *
   * @param {string} url Publicly reachable URL of an image.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {string} [options.language] The BCP-47 language code of the text to
   * be detected in the image. The default value is 'unk'. Possible values
   * include: 'unk', 'zh-Hans', 'zh-Hant', 'cs', 'da', 'nl', 'en', 'fi', 'fr',
   * 'de', 'el', 'hu', 'it', 'ja', 'ko', 'nb', 'pl', 'pt', 'ru', 'es', 'sv',
   * 'tr', 'ar', 'ro', 'sr-Cyrl', 'sr-Latn', 'sk'
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @returns {Promise} A promise is returned
   *
   * @resolve {HttpOperationResponse<OcrResult>} - The deserialized result object.
   *
   * @reject {Error} - The error object.
   */
  recognizePrintedTextWithHttpOperationResponse(detectOrientation, url, options) {
    let client = this;
    let self = this;
    return new Promise((resolve, reject) => {
      self._recognizePrintedText(detectOrientation, url, options, (err, result, request, response) => {
        let httpOperationResponse = new msRest.HttpOperationResponse(request, response);
        httpOperationResponse.body = result;
        if (err) { reject(err); }
        else { resolve(httpOperationResponse); }
        return;
      });
    });
  }

  /**
   * Optical Character Recognition (OCR) detects text in an image and extracts
   * the recognized characters into a machine-usable character stream.
   * Upon success, the OCR results will be returned.
   * Upon failure, the error code together with an error message will be
   * returned. The error code can be one of InvalidImageUrl, InvalidImageFormat,
   * InvalidImageSize, NotSupportedImage, NotSupportedLanguage, or
   * InternalServerError.
   *
   * @param {boolean} detectOrientation Whether detect the text orientation in
   * the image. With detectOrientation=true the OCR service tries to detect the
   * image orientation and correct it before further processing (e.g. if it's
   * upside-down).
   *
   * @param {string} url Publicly reachable URL of an image.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {string} [options.language] The BCP-47 language code of the text to
   * be detected in the image. The default value is 'unk'. Possible values
   * include: 'unk', 'zh-Hans', 'zh-Hant', 'cs', 'da', 'nl', 'en', 'fi', 'fr',
   * 'de', 'el', 'hu', 'it', 'ja', 'ko', 'nb', 'pl', 'pt', 'ru', 'es', 'sv',
   * 'tr', 'ar', 'ro', 'sr-Cyrl', 'sr-Latn', 'sk'
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @param {function} [optionalCallback] - The optional callback.
   *
   * @returns {function|Promise} If a callback was passed as the last parameter
   * then it returns the callback else returns a Promise.
   *
   * {Promise} A promise is returned
   *
   *                      @resolve {OcrResult} - The deserialized result object.
   *
   *                      @reject {Error} - The error object.
   *
   * {function} optionalCallback(err, result, request, response)
   *
   *                      {Error}  err        - The Error object if an error occurred, null otherwise.
   *
   *                      {object} [result]   - The deserialized result object if an error did not occur.
   *                      See {@link OcrResult} for more information.
   *
   *                      {object} [request]  - The HTTP Request object if an error did not occur.
   *
   *                      {stream} [response] - The HTTP Response stream if an error did not occur.
   */
  recognizePrintedText(detectOrientation, url, options, optionalCallback) {
    let client = this;
    let self = this;
    if (!optionalCallback && typeof options === 'function') {
      optionalCallback = options;
      options = null;
    }
    if (!optionalCallback) {
      return new Promise((resolve, reject) => {
        self._recognizePrintedText(detectOrientation, url, options, (err, result, request, response) => {
          if (err) { reject(err); }
          else { resolve(result); }
          return;
        });
      });
    } else {
      return self._recognizePrintedText(detectOrientation, url, options, optionalCallback);
    }
  }

  /**
   * This operation generates a list of words, or tags, that are relevant to the
   * content of the supplied image. The Computer Vision API can return tags based
   * on objects, living beings, scenery or actions found in images. Unlike
   * categories, tags are not organized according to a hierarchical
   * classification system, but correspond to image content. Tags may contain
   * hints to avoid ambiguity or provide context, for example the tag "cello" may
   * be accompanied by the hint "musical instrument". All tags are in English.
   * Two input methods are supported -- (1) Uploading an image or (2) specifying
   * an image URL.
   * A successful response will be returned in JSON. If the request failed, the
   * response will contain an error code and a message to help understand what
   * went wrong.
   *
   * @param {string} url Publicly reachable URL of an image.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {string} [options.language] The desired language for output
   * generation. If this parameter is not specified, the default value is
   * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
   * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
   * 'en', 'es', 'ja', 'pt', 'zh'
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @returns {Promise} A promise is returned
   *
   * @resolve {HttpOperationResponse<TagResult>} - The deserialized result object.
   *
   * @reject {Error} - The error object.
   */
  tagImageWithHttpOperationResponse(url, options) {
    let client = this;
    let self = this;
    return new Promise((resolve, reject) => {
      self._tagImage(url, options, (err, result, request, response) => {
        let httpOperationResponse = new msRest.HttpOperationResponse(request, response);
        httpOperationResponse.body = result;
        if (err) { reject(err); }
        else { resolve(httpOperationResponse); }
        return;
      });
    });
  }

  /**
   * This operation generates a list of words, or tags, that are relevant to the
   * content of the supplied image. The Computer Vision API can return tags based
   * on objects, living beings, scenery or actions found in images. Unlike
   * categories, tags are not organized according to a hierarchical
   * classification system, but correspond to image content. Tags may contain
   * hints to avoid ambiguity or provide context, for example the tag "cello" may
   * be accompanied by the hint "musical instrument". All tags are in English.
   * Two input methods are supported -- (1) Uploading an image or (2) specifying
   * an image URL.
   * A successful response will be returned in JSON. If the request failed, the
   * response will contain an error code and a message to help understand what
   * went wrong.
   *
   * @param {string} url Publicly reachable URL of an image.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {string} [options.language] The desired language for output
   * generation. If this parameter is not specified, the default value is
   * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
   * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
   * 'en', 'es', 'ja', 'pt', 'zh'
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @param {function} [optionalCallback] - The optional callback.
   *
   * @returns {function|Promise} If a callback was passed as the last parameter
   * then it returns the callback else returns a Promise.
   *
   * {Promise} A promise is returned
   *
   *                      @resolve {TagResult} - The deserialized result object.
   *
   *                      @reject {Error} - The error object.
   *
   * {function} optionalCallback(err, result, request, response)
   *
   *                      {Error}  err        - The Error object if an error occurred, null otherwise.
   *
   *                      {object} [result]   - The deserialized result object if an error did not occur.
   *                      See {@link TagResult} for more information.
   *
   *                      {object} [request]  - The HTTP Request object if an error did not occur.
   *
   *                      {stream} [response] - The HTTP Response stream if an error did not occur.
   */
  tagImage(url, options, optionalCallback) {
    let client = this;
    let self = this;
    if (!optionalCallback && typeof options === 'function') {
      optionalCallback = options;
      options = null;
    }
    if (!optionalCallback) {
      return new Promise((resolve, reject) => {
        self._tagImage(url, options, (err, result, request, response) => {
          if (err) { reject(err); }
          else { resolve(result); }
          return;
        });
      });
    } else {
      return self._tagImage(url, options, optionalCallback);
    }
  }

  /**
   * This operation generates a thumbnail image with the user-specified width and
   * height. By default, the service analyzes the image, identifies the region of
   * interest (ROI), and generates smart cropping coordinates based on the ROI.
   * Smart cropping helps when you specify an aspect ratio that differs from that
   * of the input image.
   * A successful response contains the thumbnail image binary. If the request
   * failed, the response contains an error code and a message to help determine
   * what went wrong.
   * Upon failure, the error code and an error message are returned. The error
   * code could be one of InvalidImageUrl, InvalidImageFormat, InvalidImageSize,
   * InvalidThumbnailSize, NotSupportedImage, FailedToProcess, Timeout, or
   * InternalServerError.
   *
   * @param {number} width Width of the thumbnail, in pixels. It must be between
   * 1 and 1024. Recommended minimum of 50.
   *
   * @param {number} height Height of the thumbnail, in pixels. It must be
   * between 1 and 1024. Recommended minimum of 50.
   *
   * @param {string} url Publicly reachable URL of an image.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {boolean} [options.smartCropping] Boolean flag for enabling smart
   * cropping.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @returns {Promise} A promise is returned
   *
   * @resolve {HttpOperationResponse<Object>} - The deserialized result object.
   *
   * @reject {Error} - The error object.
   */
  generateThumbnailWithHttpOperationResponse(width, height, url, options) {
    let client = this;
    let self = this;
    return new Promise((resolve, reject) => {
      self._generateThumbnail(width, height, url, options, (err, result, request, response) => {
        let httpOperationResponse = new msRest.HttpOperationResponse(request, response);
        httpOperationResponse.body = result;
        if (err) { reject(err); }
        else { resolve(httpOperationResponse); }
        return;
      });
    });
  }

  /**
   * This operation generates a thumbnail image with the user-specified width and
   * height. By default, the service analyzes the image, identifies the region of
   * interest (ROI), and generates smart cropping coordinates based on the ROI.
   * Smart cropping helps when you specify an aspect ratio that differs from that
   * of the input image.
   * A successful response contains the thumbnail image binary. If the request
   * failed, the response contains an error code and a message to help determine
   * what went wrong.
   * Upon failure, the error code and an error message are returned. The error
   * code could be one of InvalidImageUrl, InvalidImageFormat, InvalidImageSize,
   * InvalidThumbnailSize, NotSupportedImage, FailedToProcess, Timeout, or
   * InternalServerError.
   *
   * @param {number} width Width of the thumbnail, in pixels. It must be between
   * 1 and 1024. Recommended minimum of 50.
   *
   * @param {number} height Height of the thumbnail, in pixels. It must be
   * between 1 and 1024. Recommended minimum of 50.
   *
   * @param {string} url Publicly reachable URL of an image.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {boolean} [options.smartCropping] Boolean flag for enabling smart
   * cropping.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @param {function} [optionalCallback] - The optional callback.
   *
   * @returns {function|Promise} If a callback was passed as the last parameter
   * then it returns the callback else returns a Promise.
   *
   * {Promise} A promise is returned
   *
   *                      @resolve {Object} - The deserialized result object.
   *
   *                      @reject {Error} - The error object.
   *
   * {function} optionalCallback(err, result, request, response)
   *
   *                      {Error}  err        - The Error object if an error occurred, null otherwise.
   *
   *                      {object} [result]   - The deserialized result object if an error did not occur.
   *
   *                      {object} [request]  - The HTTP Request object if an error did not occur.
   *
   *                      {stream} [response] - The HTTP Response stream if an error did not occur.
   */
  generateThumbnail(width, height, url, options, optionalCallback) {
    let client = this;
    let self = this;
    if (!optionalCallback && typeof options === 'function') {
      optionalCallback = options;
      options = null;
    }
    if (!optionalCallback) {
      return new Promise((resolve, reject) => {
        self._generateThumbnail(width, height, url, options, (err, result, request, response) => {
          if (err) { reject(err); }
          else { resolve(result); }
          return;
        });
      });
    } else {
      return self._generateThumbnail(width, height, url, options, optionalCallback);
    }
  }

  /**
   * This operation returns a bounding box around the most important area of the
   * image.
   * A successful response will be returned in JSON. If the request failed, the
   * response contains an error code and a message to help determine what went
   * wrong.
   * Upon failure, the error code and an error message are returned. The error
   * code could be one of InvalidImageUrl, InvalidImageFormat, InvalidImageSize,
   * NotSupportedImage, FailedToProcess, Timeout, or InternalServerError.
   *
   * @param {string} url Publicly reachable URL of an image.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @returns {Promise} A promise is returned
   *
   * @resolve {HttpOperationResponse<AreaOfInterestResult>} - The deserialized result object.
   *
   * @reject {Error} - The error object.
   */
  getAreaOfInterestWithHttpOperationResponse(url, options) {
    let client = this;
    let self = this;
    return new Promise((resolve, reject) => {
      self._getAreaOfInterest(url, options, (err, result, request, response) => {
        let httpOperationResponse = new msRest.HttpOperationResponse(request, response);
        httpOperationResponse.body = result;
        if (err) { reject(err); }
        else { resolve(httpOperationResponse); }
        return;
      });
    });
  }

  /**
   * This operation returns a bounding box around the most important area of the
   * image.
   * A successful response will be returned in JSON. If the request failed, the
   * response contains an error code and a message to help determine what went
   * wrong.
   * Upon failure, the error code and an error message are returned. The error
   * code could be one of InvalidImageUrl, InvalidImageFormat, InvalidImageSize,
   * NotSupportedImage, FailedToProcess, Timeout, or InternalServerError.
   *
   * @param {string} url Publicly reachable URL of an image.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @param {function} [optionalCallback] - The optional callback.
   *
   * @returns {function|Promise} If a callback was passed as the last parameter
   * then it returns the callback else returns a Promise.
   *
   * {Promise} A promise is returned
   *
   *                      @resolve {AreaOfInterestResult} - The deserialized result object.
   *
   *                      @reject {Error} - The error object.
   *
   * {function} optionalCallback(err, result, request, response)
   *
   *                      {Error}  err        - The Error object if an error occurred, null otherwise.
   *
   *                      {object} [result]   - The deserialized result object if an error did not occur.
   *                      See {@link AreaOfInterestResult} for more information.
   *
   *                      {object} [request]  - The HTTP Request object if an error did not occur.
   *
   *                      {stream} [response] - The HTTP Response stream if an error did not occur.
   */
  getAreaOfInterest(url, options, optionalCallback) {
    let client = this;
    let self = this;
    if (!optionalCallback && typeof options === 'function') {
      optionalCallback = options;
      options = null;
    }
    if (!optionalCallback) {
      return new Promise((resolve, reject) => {
        self._getAreaOfInterest(url, options, (err, result, request, response) => {
          if (err) { reject(err); }
          else { resolve(result); }
          return;
        });
      });
    } else {
      return self._getAreaOfInterest(url, options, optionalCallback);
    }
  }

  /**
   * Recognize Text operation. When you use the Recognize Text interface, the
   * response contains a field called 'Operation-Location'. The
   * 'Operation-Location' field contains the URL that you must use for your Get
   * Recognize Text Operation Result operation.
   *
   * @param {string} mode Type of text to recognize. Possible values include:
   * 'Handwritten', 'Printed'
   *
   * @param {string} url Publicly reachable URL of an image.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @returns {Promise} A promise is returned
   *
   * @resolve {HttpOperationResponse<null>} - The deserialized result object.
   *
   * @reject {Error} - The error object.
   */
  recognizeTextWithHttpOperationResponse(url, mode, options) {
    let client = this;
    let self = this;
    return new Promise((resolve, reject) => {
      self._recognizeText(url, mode, options, (err, result, request, response) => {
        let httpOperationResponse = new msRest.HttpOperationResponse(request, response);
        httpOperationResponse.body = result;
        if (err) { reject(err); }
        else { resolve(httpOperationResponse); }
        return;
      });
    });
  }

  /**
   * Recognize Text operation. When you use the Recognize Text interface, the
   * response contains a field called 'Operation-Location'. The
   * 'Operation-Location' field contains the URL that you must use for your Get
   * Recognize Text Operation Result operation.
   *
   * @param {string} mode Type of text to recognize. Possible values include:
   * 'Handwritten', 'Printed'
   *
   * @param {string} url Publicly reachable URL of an image.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @param {function} [optionalCallback] - The optional callback.
   *
   * @returns {function|Promise} If a callback was passed as the last parameter
   * then it returns the callback else returns a Promise.
   *
   * {Promise} A promise is returned
   *
   *                      @resolve {null} - The deserialized result object.
   *
   *                      @reject {Error} - The error object.
   *
   * {function} optionalCallback(err, result, request, response)
   *
   *                      {Error}  err        - The Error object if an error occurred, null otherwise.
   *
   *                      {null} [result]   - The deserialized result object if an error did not occur.
   *
   *                      {object} [request]  - The HTTP Request object if an error did not occur.
   *
   *                      {stream} [response] - The HTTP Response stream if an error did not occur.
   */
  recognizeText(url, mode, options, optionalCallback) {
    let client = this;
    let self = this;
    if (!optionalCallback && typeof options === 'function') {
      optionalCallback = options;
      options = null;
    }
    if (!optionalCallback) {
      return new Promise((resolve, reject) => {
        self._recognizeText(url, mode, options, (err, result, request, response) => {
          if (err) { reject(err); }
          else { resolve(result); }
          return;
        });
      });
    } else {
      return self._recognizeText(url, mode, options, optionalCallback);
    }
  }

  /**
   * This interface is used for getting text operation result. The URL to this
   * interface should be retrieved from 'Operation-Location' field returned from
   * Recognize Text interface.
   *
   * @param {string} operationId Id of the text operation returned in the
   * response of the 'Recognize Text'
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @returns {Promise} A promise is returned
   *
   * @resolve {HttpOperationResponse<TextOperationResult>} - The deserialized result object.
   *
   * @reject {Error} - The error object.
   */
  getTextOperationResultWithHttpOperationResponse(operationId, options) {
    let client = this;
    let self = this;
    return new Promise((resolve, reject) => {
      self._getTextOperationResult(operationId, options, (err, result, request, response) => {
        let httpOperationResponse = new msRest.HttpOperationResponse(request, response);
        httpOperationResponse.body = result;
        if (err) { reject(err); }
        else { resolve(httpOperationResponse); }
        return;
      });
    });
  }

  /**
   * This interface is used for getting text operation result. The URL to this
   * interface should be retrieved from 'Operation-Location' field returned from
   * Recognize Text interface.
   *
   * @param {string} operationId Id of the text operation returned in the
   * response of the 'Recognize Text'
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @param {function} [optionalCallback] - The optional callback.
   *
   * @returns {function|Promise} If a callback was passed as the last parameter
   * then it returns the callback else returns a Promise.
   *
   * {Promise} A promise is returned
   *
   *                      @resolve {TextOperationResult} - The deserialized result object.
   *
   *                      @reject {Error} - The error object.
   *
   * {function} optionalCallback(err, result, request, response)
   *
   *                      {Error}  err        - The Error object if an error occurred, null otherwise.
   *
   *                      {object} [result]   - The deserialized result object if an error did not occur.
   *                      See {@link TextOperationResult} for more information.
   *
   *                      {object} [request]  - The HTTP Request object if an error did not occur.
   *
   *                      {stream} [response] - The HTTP Response stream if an error did not occur.
   */
  getTextOperationResult(operationId, options, optionalCallback) {
    let client = this;
    let self = this;
    if (!optionalCallback && typeof options === 'function') {
      optionalCallback = options;
      options = null;
    }
    if (!optionalCallback) {
      return new Promise((resolve, reject) => {
        self._getTextOperationResult(operationId, options, (err, result, request, response) => {
          if (err) { reject(err); }
          else { resolve(result); }
          return;
        });
      });
    } else {
      return self._getTextOperationResult(operationId, options, optionalCallback);
    }
  }

  /**
   * Use this interface to get the result of a Read operation, employing the
   * state-of-the-art Optical Character Recognition (OCR) algorithms optimized
   * for text-heavy documents. When you use the Read File interface, the response
   * contains a field called "Operation-Location". The "Operation-Location" field
   * contains the URL that you must use for your "Read Operation Result"
   * operation to access OCR results.​
   *
   * @param {string} mode Type of text to recognize. Possible values include:
   * 'Handwritten', 'Printed'
   *
   * @param {string} url Publicly reachable URL of an image.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @returns {Promise} A promise is returned
   *
   * @resolve {HttpOperationResponse<null>} - The deserialized result object.
   *
   * @reject {Error} - The error object.
   */
  batchReadFileWithHttpOperationResponse(url, mode, options) {
    let client = this;
    let self = this;
    return new Promise((resolve, reject) => {
      self._batchReadFile(url, mode, options, (err, result, request, response) => {
        let httpOperationResponse = new msRest.HttpOperationResponse(request, response);
        httpOperationResponse.body = result;
        if (err) { reject(err); }
        else { resolve(httpOperationResponse); }
        return;
      });
    });
  }

  /**
   * Use this interface to get the result of a Read operation, employing the
   * state-of-the-art Optical Character Recognition (OCR) algorithms optimized
   * for text-heavy documents. When you use the Read File interface, the response
   * contains a field called "Operation-Location". The "Operation-Location" field
   * contains the URL that you must use for your "Read Operation Result"
   * operation to access OCR results.​
   *
   * @param {string} mode Type of text to recognize. Possible values include:
   * 'Handwritten', 'Printed'
   *
   * @param {string} url Publicly reachable URL of an image.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @param {function} [optionalCallback] - The optional callback.
   *
   * @returns {function|Promise} If a callback was passed as the last parameter
   * then it returns the callback else returns a Promise.
   *
   * {Promise} A promise is returned
   *
   *                      @resolve {null} - The deserialized result object.
   *
   *                      @reject {Error} - The error object.
   *
   * {function} optionalCallback(err, result, request, response)
   *
   *                      {Error}  err        - The Error object if an error occurred, null otherwise.
   *
   *                      {null} [result]   - The deserialized result object if an error did not occur.
   *
   *                      {object} [request]  - The HTTP Request object if an error did not occur.
   *
   *                      {stream} [response] - The HTTP Response stream if an error did not occur.
   */
  batchReadFile(url, mode, options, optionalCallback) {
    let client = this;
    let self = this;
    if (!optionalCallback && typeof options === 'function') {
      optionalCallback = options;
      options = null;
    }
    if (!optionalCallback) {
      return new Promise((resolve, reject) => {
        self._batchReadFile(url, mode, options, (err, result, request, response) => {
          if (err) { reject(err); }
          else { resolve(result); }
          return;
        });
      });
    } else {
      return self._batchReadFile(url, mode, options, optionalCallback);
    }
  }

  /**
   * This interface is used for getting OCR results of Read operation. The URL to
   * this interface should be retrieved from "Operation-Location" field returned
   * from Batch Read File interface.
   *
   * @param {string} operationId Id of read operation returned in the response of
   * the "Batch Read File" interface.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @returns {Promise} A promise is returned
   *
   * @resolve {HttpOperationResponse<ReadOperationResult>} - The deserialized result object.
   *
   * @reject {Error} - The error object.
   */
  getReadOperationResultWithHttpOperationResponse(operationId, options) {
    let client = this;
    let self = this;
    return new Promise((resolve, reject) => {
      self._getReadOperationResult(operationId, options, (err, result, request, response) => {
        let httpOperationResponse = new msRest.HttpOperationResponse(request, response);
        httpOperationResponse.body = result;
        if (err) { reject(err); }
        else { resolve(httpOperationResponse); }
        return;
      });
    });
  }

  /**
   * This interface is used for getting OCR results of Read operation. The URL to
   * this interface should be retrieved from "Operation-Location" field returned
   * from Batch Read File interface.
   *
   * @param {string} operationId Id of read operation returned in the response of
   * the "Batch Read File" interface.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @param {function} [optionalCallback] - The optional callback.
   *
   * @returns {function|Promise} If a callback was passed as the last parameter
   * then it returns the callback else returns a Promise.
   *
   * {Promise} A promise is returned
   *
   *                      @resolve {ReadOperationResult} - The deserialized result object.
   *
   *                      @reject {Error} - The error object.
   *
   * {function} optionalCallback(err, result, request, response)
   *
   *                      {Error}  err        - The Error object if an error occurred, null otherwise.
   *
   *                      {object} [result]   - The deserialized result object if an error did not occur.
   *                      See {@link ReadOperationResult} for more information.
   *
   *                      {object} [request]  - The HTTP Request object if an error did not occur.
   *
   *                      {stream} [response] - The HTTP Response stream if an error did not occur.
   */
  getReadOperationResult(operationId, options, optionalCallback) {
    let client = this;
    let self = this;
    if (!optionalCallback && typeof options === 'function') {
      optionalCallback = options;
      options = null;
    }
    if (!optionalCallback) {
      return new Promise((resolve, reject) => {
        self._getReadOperationResult(operationId, options, (err, result, request, response) => {
          if (err) { reject(err); }
          else { resolve(result); }
          return;
        });
      });
    } else {
      return self._getReadOperationResult(operationId, options, optionalCallback);
    }
  }

  /**
   * This operation extracts a rich set of visual features based on the image
   * content.
   * Two input methods are supported -- (1) Uploading an image or (2) specifying
   * an image URL. Within your request, there is an optional parameter to allow
   * you to choose which features to return. By default, image categories are
   * returned in the response.
   * A successful response will be returned in JSON. If the request failed, the
   * response will contain an error code and a message to help understand what
   * went wrong.
   *
   * @param {object} image An image stream.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {array} [options.visualFeatures] A string indicating what visual
   * feature types to return. Multiple values should be comma-separated. Valid
   * visual feature types include: Categories - categorizes image content
   * according to a taxonomy defined in documentation. Tags - tags the image with
   * a detailed list of words related to the image content. Description -
   * describes the image content with a complete English sentence. Faces -
   * detects if faces are present. If present, generate coordinates, gender and
   * age. ImageType - detects if image is clipart or a line drawing. Color -
   * determines the accent color, dominant color, and whether an image is
   * black&white. Adult - detects if the image is pornographic in nature (depicts
   * nudity or a sex act).  Sexually suggestive content is also detected. Objects
   * - detects various objects within an image, including the approximate
   * location. The Objects argument is only available in English. Brands -
   * detects various brands within an image, including the approximate location.
   * The Brands argument is only available in English.
   *
   * @param {array} [options.details] A string indicating which domain-specific
   * details to return. Multiple values should be comma-separated. Valid visual
   * feature types include: Celebrities - identifies celebrities if detected in
   * the image, Landmarks - identifies notable landmarks in the image.
   *
   * @param {string} [options.language] The desired language for output
   * generation. If this parameter is not specified, the default value is
   * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
   * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
   * 'en', 'es', 'ja', 'pt', 'zh'
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @returns {Promise} A promise is returned
   *
   * @resolve {HttpOperationResponse<ImageAnalysis>} - The deserialized result object.
   *
   * @reject {Error} - The error object.
   */
  analyzeImageInStreamWithHttpOperationResponse(image, options) {
    let client = this;
    let self = this;
    return new Promise((resolve, reject) => {
      self._analyzeImageInStream(image, options, (err, result, request, response) => {
        let httpOperationResponse = new msRest.HttpOperationResponse(request, response);
        httpOperationResponse.body = result;
        if (err) { reject(err); }
        else { resolve(httpOperationResponse); }
        return;
      });
    });
  }

  /**
   * This operation extracts a rich set of visual features based on the image
   * content.
   * Two input methods are supported -- (1) Uploading an image or (2) specifying
   * an image URL. Within your request, there is an optional parameter to allow
   * you to choose which features to return. By default, image categories are
   * returned in the response.
   * A successful response will be returned in JSON. If the request failed, the
   * response will contain an error code and a message to help understand what
   * went wrong.
   *
   * @param {object} image An image stream.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {array} [options.visualFeatures] A string indicating what visual
   * feature types to return. Multiple values should be comma-separated. Valid
   * visual feature types include: Categories - categorizes image content
   * according to a taxonomy defined in documentation. Tags - tags the image with
   * a detailed list of words related to the image content. Description -
   * describes the image content with a complete English sentence. Faces -
   * detects if faces are present. If present, generate coordinates, gender and
   * age. ImageType - detects if image is clipart or a line drawing. Color -
   * determines the accent color, dominant color, and whether an image is
   * black&white. Adult - detects if the image is pornographic in nature (depicts
   * nudity or a sex act).  Sexually suggestive content is also detected. Objects
   * - detects various objects within an image, including the approximate
   * location. The Objects argument is only available in English. Brands -
   * detects various brands within an image, including the approximate location.
   * The Brands argument is only available in English.
   *
   * @param {array} [options.details] A string indicating which domain-specific
   * details to return. Multiple values should be comma-separated. Valid visual
   * feature types include: Celebrities - identifies celebrities if detected in
   * the image, Landmarks - identifies notable landmarks in the image.
   *
   * @param {string} [options.language] The desired language for output
   * generation. If this parameter is not specified, the default value is
   * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
   * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
   * 'en', 'es', 'ja', 'pt', 'zh'
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @param {function} [optionalCallback] - The optional callback.
   *
   * @returns {function|Promise} If a callback was passed as the last parameter
   * then it returns the callback else returns a Promise.
   *
   * {Promise} A promise is returned
   *
   *                      @resolve {ImageAnalysis} - The deserialized result object.
   *
   *                      @reject {Error} - The error object.
   *
   * {function} optionalCallback(err, result, request, response)
   *
   *                      {Error}  err        - The Error object if an error occurred, null otherwise.
   *
   *                      {object} [result]   - The deserialized result object if an error did not occur.
   *                      See {@link ImageAnalysis} for more information.
   *
   *                      {object} [request]  - The HTTP Request object if an error did not occur.
   *
   *                      {stream} [response] - The HTTP Response stream if an error did not occur.
   */
  analyzeImageInStream(image, options, optionalCallback) {
    let client = this;
    let self = this;
    if (!optionalCallback && typeof options === 'function') {
      optionalCallback = options;
      options = null;
    }
    if (!optionalCallback) {
      return new Promise((resolve, reject) => {
        self._analyzeImageInStream(image, options, (err, result, request, response) => {
          if (err) { reject(err); }
          else { resolve(result); }
          return;
        });
      });
    } else {
      return self._analyzeImageInStream(image, options, optionalCallback);
    }
  }

  /**
   * This operation returns a bounding box around the most important area of the
   * image.
   * A successful response will be returned in JSON. If the request failed, the
   * response contains an error code and a message to help determine what went
   * wrong.
   * Upon failure, the error code and an error message are returned. The error
   * code could be one of InvalidImageUrl, InvalidImageFormat, InvalidImageSize,
   * NotSupportedImage, FailedToProcess, Timeout, or InternalServerError.
   *
   * @param {object} image An image stream.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @returns {Promise} A promise is returned
   *
   * @resolve {HttpOperationResponse<AreaOfInterestResult>} - The deserialized result object.
   *
   * @reject {Error} - The error object.
   */
  getAreaOfInterestInStreamWithHttpOperationResponse(image, options) {
    let client = this;
    let self = this;
    return new Promise((resolve, reject) => {
      self._getAreaOfInterestInStream(image, options, (err, result, request, response) => {
        let httpOperationResponse = new msRest.HttpOperationResponse(request, response);
        httpOperationResponse.body = result;
        if (err) { reject(err); }
        else { resolve(httpOperationResponse); }
        return;
      });
    });
  }

  /**
   * This operation returns a bounding box around the most important area of the
   * image.
   * A successful response will be returned in JSON. If the request failed, the
   * response contains an error code and a message to help determine what went
   * wrong.
   * Upon failure, the error code and an error message are returned. The error
   * code could be one of InvalidImageUrl, InvalidImageFormat, InvalidImageSize,
   * NotSupportedImage, FailedToProcess, Timeout, or InternalServerError.
   *
   * @param {object} image An image stream.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @param {function} [optionalCallback] - The optional callback.
   *
   * @returns {function|Promise} If a callback was passed as the last parameter
   * then it returns the callback else returns a Promise.
   *
   * {Promise} A promise is returned
   *
   *                      @resolve {AreaOfInterestResult} - The deserialized result object.
   *
   *                      @reject {Error} - The error object.
   *
   * {function} optionalCallback(err, result, request, response)
   *
   *                      {Error}  err        - The Error object if an error occurred, null otherwise.
   *
   *                      {object} [result]   - The deserialized result object if an error did not occur.
   *                      See {@link AreaOfInterestResult} for more information.
   *
   *                      {object} [request]  - The HTTP Request object if an error did not occur.
   *
   *                      {stream} [response] - The HTTP Response stream if an error did not occur.
   */
  getAreaOfInterestInStream(image, options, optionalCallback) {
    let client = this;
    let self = this;
    if (!optionalCallback && typeof options === 'function') {
      optionalCallback = options;
      options = null;
    }
    if (!optionalCallback) {
      return new Promise((resolve, reject) => {
        self._getAreaOfInterestInStream(image, options, (err, result, request, response) => {
          if (err) { reject(err); }
          else { resolve(result); }
          return;
        });
      });
    } else {
      return self._getAreaOfInterestInStream(image, options, optionalCallback);
    }
  }

  /**
   * This operation generates a description of an image in human readable
   * language with complete sentences. The description is based on a collection
   * of content tags, which are also returned by the operation. More than one
   * description can be generated for each image. Descriptions are ordered by
   * their confidence score. All descriptions are in English.
   * Two input methods are supported -- (1) Uploading an image or (2) specifying
   * an image URL.
   * A successful response will be returned in JSON. If the request failed, the
   * response will contain an error code and a message to help understand what
   * went wrong.
   *
   * @param {object} image An image stream.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {number} [options.maxCandidates] Maximum number of candidate
   * descriptions to be returned.  The default is 1.
   *
   * @param {string} [options.language] The desired language for output
   * generation. If this parameter is not specified, the default value is
   * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
   * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
   * 'en', 'es', 'ja', 'pt', 'zh'
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @returns {Promise} A promise is returned
   *
   * @resolve {HttpOperationResponse<ImageDescription>} - The deserialized result object.
   *
   * @reject {Error} - The error object.
   */
  describeImageInStreamWithHttpOperationResponse(image, options) {
    let client = this;
    let self = this;
    return new Promise((resolve, reject) => {
      self._describeImageInStream(image, options, (err, result, request, response) => {
        let httpOperationResponse = new msRest.HttpOperationResponse(request, response);
        httpOperationResponse.body = result;
        if (err) { reject(err); }
        else { resolve(httpOperationResponse); }
        return;
      });
    });
  }

  /**
   * This operation generates a description of an image in human readable
   * language with complete sentences. The description is based on a collection
   * of content tags, which are also returned by the operation. More than one
   * description can be generated for each image. Descriptions are ordered by
   * their confidence score. All descriptions are in English.
   * Two input methods are supported -- (1) Uploading an image or (2) specifying
   * an image URL.
   * A successful response will be returned in JSON. If the request failed, the
   * response will contain an error code and a message to help understand what
   * went wrong.
   *
   * @param {object} image An image stream.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {number} [options.maxCandidates] Maximum number of candidate
   * descriptions to be returned.  The default is 1.
   *
   * @param {string} [options.language] The desired language for output
   * generation. If this parameter is not specified, the default value is
   * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
   * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
   * 'en', 'es', 'ja', 'pt', 'zh'
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @param {function} [optionalCallback] - The optional callback.
   *
   * @returns {function|Promise} If a callback was passed as the last parameter
   * then it returns the callback else returns a Promise.
   *
   * {Promise} A promise is returned
   *
   *                      @resolve {ImageDescription} - The deserialized result object.
   *
   *                      @reject {Error} - The error object.
   *
   * {function} optionalCallback(err, result, request, response)
   *
   *                      {Error}  err        - The Error object if an error occurred, null otherwise.
   *
   *                      {object} [result]   - The deserialized result object if an error did not occur.
   *                      See {@link ImageDescription} for more information.
   *
   *                      {object} [request]  - The HTTP Request object if an error did not occur.
   *
   *                      {stream} [response] - The HTTP Response stream if an error did not occur.
   */
  describeImageInStream(image, options, optionalCallback) {
    let client = this;
    let self = this;
    if (!optionalCallback && typeof options === 'function') {
      optionalCallback = options;
      options = null;
    }
    if (!optionalCallback) {
      return new Promise((resolve, reject) => {
        self._describeImageInStream(image, options, (err, result, request, response) => {
          if (err) { reject(err); }
          else { resolve(result); }
          return;
        });
      });
    } else {
      return self._describeImageInStream(image, options, optionalCallback);
    }
  }

  /**
   * Performs object detection on the specified image.
   * Two input methods are supported -- (1) Uploading an image or (2) specifying
   * an image URL.
   * A successful response will be returned in JSON. If the request failed, the
   * response will contain an error code and a message to help understand what
   * went wrong.
   *
   * @param {object} image An image stream.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @returns {Promise} A promise is returned
   *
   * @resolve {HttpOperationResponse<DetectResult>} - The deserialized result object.
   *
   * @reject {Error} - The error object.
   */
  detectObjectsInStreamWithHttpOperationResponse(image, options) {
    let client = this;
    let self = this;
    return new Promise((resolve, reject) => {
      self._detectObjectsInStream(image, options, (err, result, request, response) => {
        let httpOperationResponse = new msRest.HttpOperationResponse(request, response);
        httpOperationResponse.body = result;
        if (err) { reject(err); }
        else { resolve(httpOperationResponse); }
        return;
      });
    });
  }

  /**
   * Performs object detection on the specified image.
   * Two input methods are supported -- (1) Uploading an image or (2) specifying
   * an image URL.
   * A successful response will be returned in JSON. If the request failed, the
   * response will contain an error code and a message to help understand what
   * went wrong.
   *
   * @param {object} image An image stream.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @param {function} [optionalCallback] - The optional callback.
   *
   * @returns {function|Promise} If a callback was passed as the last parameter
   * then it returns the callback else returns a Promise.
   *
   * {Promise} A promise is returned
   *
   *                      @resolve {DetectResult} - The deserialized result object.
   *
   *                      @reject {Error} - The error object.
   *
   * {function} optionalCallback(err, result, request, response)
   *
   *                      {Error}  err        - The Error object if an error occurred, null otherwise.
   *
   *                      {object} [result]   - The deserialized result object if an error did not occur.
   *                      See {@link DetectResult} for more information.
   *
   *                      {object} [request]  - The HTTP Request object if an error did not occur.
   *
   *                      {stream} [response] - The HTTP Response stream if an error did not occur.
   */
  detectObjectsInStream(image, options, optionalCallback) {
    let client = this;
    let self = this;
    if (!optionalCallback && typeof options === 'function') {
      optionalCallback = options;
      options = null;
    }
    if (!optionalCallback) {
      return new Promise((resolve, reject) => {
        self._detectObjectsInStream(image, options, (err, result, request, response) => {
          if (err) { reject(err); }
          else { resolve(result); }
          return;
        });
      });
    } else {
      return self._detectObjectsInStream(image, options, optionalCallback);
    }
  }

  /**
   * This operation generates a thumbnail image with the user-specified width and
   * height. By default, the service analyzes the image, identifies the region of
   * interest (ROI), and generates smart cropping coordinates based on the ROI.
   * Smart cropping helps when you specify an aspect ratio that differs from that
   * of the input image.
   * A successful response contains the thumbnail image binary. If the request
   * failed, the response contains an error code and a message to help determine
   * what went wrong.
   * Upon failure, the error code and an error message are returned. The error
   * code could be one of InvalidImageUrl, InvalidImageFormat, InvalidImageSize,
   * InvalidThumbnailSize, NotSupportedImage, FailedToProcess, Timeout, or
   * InternalServerError.
   *
   * @param {number} width Width of the thumbnail, in pixels. It must be between
   * 1 and 1024. Recommended minimum of 50.
   *
   * @param {number} height Height of the thumbnail, in pixels. It must be
   * between 1 and 1024. Recommended minimum of 50.
   *
   * @param {object} image An image stream.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {boolean} [options.smartCropping] Boolean flag for enabling smart
   * cropping.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @returns {Promise} A promise is returned
   *
   * @resolve {HttpOperationResponse<Object>} - The deserialized result object.
   *
   * @reject {Error} - The error object.
   */
  generateThumbnailInStreamWithHttpOperationResponse(width, height, image, options) {
    let client = this;
    let self = this;
    return new Promise((resolve, reject) => {
      self._generateThumbnailInStream(width, height, image, options, (err, result, request, response) => {
        let httpOperationResponse = new msRest.HttpOperationResponse(request, response);
        httpOperationResponse.body = result;
        if (err) { reject(err); }
        else { resolve(httpOperationResponse); }
        return;
      });
    });
  }

  /**
   * This operation generates a thumbnail image with the user-specified width and
   * height. By default, the service analyzes the image, identifies the region of
   * interest (ROI), and generates smart cropping coordinates based on the ROI.
   * Smart cropping helps when you specify an aspect ratio that differs from that
   * of the input image.
   * A successful response contains the thumbnail image binary. If the request
   * failed, the response contains an error code and a message to help determine
   * what went wrong.
   * Upon failure, the error code and an error message are returned. The error
   * code could be one of InvalidImageUrl, InvalidImageFormat, InvalidImageSize,
   * InvalidThumbnailSize, NotSupportedImage, FailedToProcess, Timeout, or
   * InternalServerError.
   *
   * @param {number} width Width of the thumbnail, in pixels. It must be between
   * 1 and 1024. Recommended minimum of 50.
   *
   * @param {number} height Height of the thumbnail, in pixels. It must be
   * between 1 and 1024. Recommended minimum of 50.
   *
   * @param {object} image An image stream.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {boolean} [options.smartCropping] Boolean flag for enabling smart
   * cropping.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @param {function} [optionalCallback] - The optional callback.
   *
   * @returns {function|Promise} If a callback was passed as the last parameter
   * then it returns the callback else returns a Promise.
   *
   * {Promise} A promise is returned
   *
   *                      @resolve {Object} - The deserialized result object.
   *
   *                      @reject {Error} - The error object.
   *
   * {function} optionalCallback(err, result, request, response)
   *
   *                      {Error}  err        - The Error object if an error occurred, null otherwise.
   *
   *                      {object} [result]   - The deserialized result object if an error did not occur.
   *
   *                      {object} [request]  - The HTTP Request object if an error did not occur.
   *
   *                      {stream} [response] - The HTTP Response stream if an error did not occur.
   */
  generateThumbnailInStream(width, height, image, options, optionalCallback) {
    let client = this;
    let self = this;
    if (!optionalCallback && typeof options === 'function') {
      optionalCallback = options;
      options = null;
    }
    if (!optionalCallback) {
      return new Promise((resolve, reject) => {
        self._generateThumbnailInStream(width, height, image, options, (err, result, request, response) => {
          if (err) { reject(err); }
          else { resolve(result); }
          return;
        });
      });
    } else {
      return self._generateThumbnailInStream(width, height, image, options, optionalCallback);
    }
  }

  /**
   * This operation recognizes content within an image by applying a
   * domain-specific model. The list of domain-specific models that are supported
   * by the Computer Vision API can be retrieved using the /models GET request.
   * Currently, the API provides following domain-specific models: celebrities,
   * landmarks.
   * Two input methods are supported -- (1) Uploading an image or (2) specifying
   * an image URL.
   * A successful response will be returned in JSON.
   * If the request failed, the response will contain an error code and a message
   * to help understand what went wrong.
   *
   * @param {string} model The domain-specific content to recognize.
   *
   * @param {object} image An image stream.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {string} [options.language] The desired language for output
   * generation. If this parameter is not specified, the default value is
   * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
   * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
   * 'en', 'es', 'ja', 'pt', 'zh'
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @returns {Promise} A promise is returned
   *
   * @resolve {HttpOperationResponse<DomainModelResults>} - The deserialized result object.
   *
   * @reject {Error} - The error object.
   */
  analyzeImageByDomainInStreamWithHttpOperationResponse(model, image, options) {
    let client = this;
    let self = this;
    return new Promise((resolve, reject) => {
      self._analyzeImageByDomainInStream(model, image, options, (err, result, request, response) => {
        let httpOperationResponse = new msRest.HttpOperationResponse(request, response);
        httpOperationResponse.body = result;
        if (err) { reject(err); }
        else { resolve(httpOperationResponse); }
        return;
      });
    });
  }

  /**
   * This operation recognizes content within an image by applying a
   * domain-specific model. The list of domain-specific models that are supported
   * by the Computer Vision API can be retrieved using the /models GET request.
   * Currently, the API provides following domain-specific models: celebrities,
   * landmarks.
   * Two input methods are supported -- (1) Uploading an image or (2) specifying
   * an image URL.
   * A successful response will be returned in JSON.
   * If the request failed, the response will contain an error code and a message
   * to help understand what went wrong.
   *
   * @param {string} model The domain-specific content to recognize.
   *
   * @param {object} image An image stream.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {string} [options.language] The desired language for output
   * generation. If this parameter is not specified, the default value is
   * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
   * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
   * 'en', 'es', 'ja', 'pt', 'zh'
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @param {function} [optionalCallback] - The optional callback.
   *
   * @returns {function|Promise} If a callback was passed as the last parameter
   * then it returns the callback else returns a Promise.
   *
   * {Promise} A promise is returned
   *
   *                      @resolve {DomainModelResults} - The deserialized result object.
   *
   *                      @reject {Error} - The error object.
   *
   * {function} optionalCallback(err, result, request, response)
   *
   *                      {Error}  err        - The Error object if an error occurred, null otherwise.
   *
   *                      {object} [result]   - The deserialized result object if an error did not occur.
   *                      See {@link DomainModelResults} for more information.
   *
   *                      {object} [request]  - The HTTP Request object if an error did not occur.
   *
   *                      {stream} [response] - The HTTP Response stream if an error did not occur.
   */
  analyzeImageByDomainInStream(model, image, options, optionalCallback) {
    let client = this;
    let self = this;
    if (!optionalCallback && typeof options === 'function') {
      optionalCallback = options;
      options = null;
    }
    if (!optionalCallback) {
      return new Promise((resolve, reject) => {
        self._analyzeImageByDomainInStream(model, image, options, (err, result, request, response) => {
          if (err) { reject(err); }
          else { resolve(result); }
          return;
        });
      });
    } else {
      return self._analyzeImageByDomainInStream(model, image, options, optionalCallback);
    }
  }

  /**
   * Optical Character Recognition (OCR) detects text in an image and extracts
   * the recognized characters into a machine-usable character stream.
   * Upon success, the OCR results will be returned.
   * Upon failure, the error code together with an error message will be
   * returned. The error code can be one of InvalidImageUrl, InvalidImageFormat,
   * InvalidImageSize, NotSupportedImage, NotSupportedLanguage, or
   * InternalServerError.
   *
   * @param {boolean} detectOrientation Whether detect the text orientation in
   * the image. With detectOrientation=true the OCR service tries to detect the
   * image orientation and correct it before further processing (e.g. if it's
   * upside-down).
   *
   * @param {object} image An image stream.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {string} [options.language] The BCP-47 language code of the text to
   * be detected in the image. The default value is 'unk'. Possible values
   * include: 'unk', 'zh-Hans', 'zh-Hant', 'cs', 'da', 'nl', 'en', 'fi', 'fr',
   * 'de', 'el', 'hu', 'it', 'ja', 'ko', 'nb', 'pl', 'pt', 'ru', 'es', 'sv',
   * 'tr', 'ar', 'ro', 'sr-Cyrl', 'sr-Latn', 'sk'
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @returns {Promise} A promise is returned
   *
   * @resolve {HttpOperationResponse<OcrResult>} - The deserialized result object.
   *
   * @reject {Error} - The error object.
   */
  recognizePrintedTextInStreamWithHttpOperationResponse(detectOrientation, image, options) {
    let client = this;
    let self = this;
    return new Promise((resolve, reject) => {
      self._recognizePrintedTextInStream(detectOrientation, image, options, (err, result, request, response) => {
        let httpOperationResponse = new msRest.HttpOperationResponse(request, response);
        httpOperationResponse.body = result;
        if (err) { reject(err); }
        else { resolve(httpOperationResponse); }
        return;
      });
    });
  }

  /**
   * Optical Character Recognition (OCR) detects text in an image and extracts
   * the recognized characters into a machine-usable character stream.
   * Upon success, the OCR results will be returned.
   * Upon failure, the error code together with an error message will be
   * returned. The error code can be one of InvalidImageUrl, InvalidImageFormat,
   * InvalidImageSize, NotSupportedImage, NotSupportedLanguage, or
   * InternalServerError.
   *
   * @param {boolean} detectOrientation Whether detect the text orientation in
   * the image. With detectOrientation=true the OCR service tries to detect the
   * image orientation and correct it before further processing (e.g. if it's
   * upside-down).
   *
   * @param {object} image An image stream.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {string} [options.language] The BCP-47 language code of the text to
   * be detected in the image. The default value is 'unk'. Possible values
   * include: 'unk', 'zh-Hans', 'zh-Hant', 'cs', 'da', 'nl', 'en', 'fi', 'fr',
   * 'de', 'el', 'hu', 'it', 'ja', 'ko', 'nb', 'pl', 'pt', 'ru', 'es', 'sv',
   * 'tr', 'ar', 'ro', 'sr-Cyrl', 'sr-Latn', 'sk'
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @param {function} [optionalCallback] - The optional callback.
   *
   * @returns {function|Promise} If a callback was passed as the last parameter
   * then it returns the callback else returns a Promise.
   *
   * {Promise} A promise is returned
   *
   *                      @resolve {OcrResult} - The deserialized result object.
   *
   *                      @reject {Error} - The error object.
   *
   * {function} optionalCallback(err, result, request, response)
   *
   *                      {Error}  err        - The Error object if an error occurred, null otherwise.
   *
   *                      {object} [result]   - The deserialized result object if an error did not occur.
   *                      See {@link OcrResult} for more information.
   *
   *                      {object} [request]  - The HTTP Request object if an error did not occur.
   *
   *                      {stream} [response] - The HTTP Response stream if an error did not occur.
   */
  recognizePrintedTextInStream(detectOrientation, image, options, optionalCallback) {
    let client = this;
    let self = this;
    if (!optionalCallback && typeof options === 'function') {
      optionalCallback = options;
      options = null;
    }
    if (!optionalCallback) {
      return new Promise((resolve, reject) => {
        self._recognizePrintedTextInStream(detectOrientation, image, options, (err, result, request, response) => {
          if (err) { reject(err); }
          else { resolve(result); }
          return;
        });
      });
    } else {
      return self._recognizePrintedTextInStream(detectOrientation, image, options, optionalCallback);
    }
  }

  /**
   * This operation generates a list of words, or tags, that are relevant to the
   * content of the supplied image. The Computer Vision API can return tags based
   * on objects, living beings, scenery or actions found in images. Unlike
   * categories, tags are not organized according to a hierarchical
   * classification system, but correspond to image content. Tags may contain
   * hints to avoid ambiguity or provide context, for example the tag "cello" may
   * be accompanied by the hint "musical instrument". All tags are in English.
   * Two input methods are supported -- (1) Uploading an image or (2) specifying
   * an image URL.
   * A successful response will be returned in JSON. If the request failed, the
   * response will contain an error code and a message to help understand what
   * went wrong.
   *
   * @param {object} image An image stream.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {string} [options.language] The desired language for output
   * generation. If this parameter is not specified, the default value is
   * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
   * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
   * 'en', 'es', 'ja', 'pt', 'zh'
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @returns {Promise} A promise is returned
   *
   * @resolve {HttpOperationResponse<TagResult>} - The deserialized result object.
   *
   * @reject {Error} - The error object.
   */
  tagImageInStreamWithHttpOperationResponse(image, options) {
    let client = this;
    let self = this;
    return new Promise((resolve, reject) => {
      self._tagImageInStream(image, options, (err, result, request, response) => {
        let httpOperationResponse = new msRest.HttpOperationResponse(request, response);
        httpOperationResponse.body = result;
        if (err) { reject(err); }
        else { resolve(httpOperationResponse); }
        return;
      });
    });
  }

  /**
   * This operation generates a list of words, or tags, that are relevant to the
   * content of the supplied image. The Computer Vision API can return tags based
   * on objects, living beings, scenery or actions found in images. Unlike
   * categories, tags are not organized according to a hierarchical
   * classification system, but correspond to image content. Tags may contain
   * hints to avoid ambiguity or provide context, for example the tag "cello" may
   * be accompanied by the hint "musical instrument". All tags are in English.
   * Two input methods are supported -- (1) Uploading an image or (2) specifying
   * an image URL.
   * A successful response will be returned in JSON. If the request failed, the
   * response will contain an error code and a message to help understand what
   * went wrong.
   *
   * @param {object} image An image stream.
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {string} [options.language] The desired language for output
   * generation. If this parameter is not specified, the default value is
   * &quot;en&quot;.Supported languages:en - English, Default. es - Spanish, ja -
   * Japanese, pt - Portuguese, zh - Simplified Chinese. Possible values include:
   * 'en', 'es', 'ja', 'pt', 'zh'
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @param {function} [optionalCallback] - The optional callback.
   *
   * @returns {function|Promise} If a callback was passed as the last parameter
   * then it returns the callback else returns a Promise.
   *
   * {Promise} A promise is returned
   *
   *                      @resolve {TagResult} - The deserialized result object.
   *
   *                      @reject {Error} - The error object.
   *
   * {function} optionalCallback(err, result, request, response)
   *
   *                      {Error}  err        - The Error object if an error occurred, null otherwise.
   *
   *                      {object} [result]   - The deserialized result object if an error did not occur.
   *                      See {@link TagResult} for more information.
   *
   *                      {object} [request]  - The HTTP Request object if an error did not occur.
   *
   *                      {stream} [response] - The HTTP Response stream if an error did not occur.
   */
  tagImageInStream(image, options, optionalCallback) {
    let client = this;
    let self = this;
    if (!optionalCallback && typeof options === 'function') {
      optionalCallback = options;
      options = null;
    }
    if (!optionalCallback) {
      return new Promise((resolve, reject) => {
        self._tagImageInStream(image, options, (err, result, request, response) => {
          if (err) { reject(err); }
          else { resolve(result); }
          return;
        });
      });
    } else {
      return self._tagImageInStream(image, options, optionalCallback);
    }
  }

  /**
   * Recognize Text operation. When you use the Recognize Text interface, the
   * response contains a field called 'Operation-Location'. The
   * 'Operation-Location' field contains the URL that you must use for your Get
   * Recognize Text Operation Result operation.
   *
   * @param {object} image An image stream.
   *
   * @param {string} mode Type of text to recognize. Possible values include:
   * 'Handwritten', 'Printed'
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @returns {Promise} A promise is returned
   *
   * @resolve {HttpOperationResponse<null>} - The deserialized result object.
   *
   * @reject {Error} - The error object.
   */
  recognizeTextInStreamWithHttpOperationResponse(image, mode, options) {
    let client = this;
    let self = this;
    return new Promise((resolve, reject) => {
      self._recognizeTextInStream(image, mode, options, (err, result, request, response) => {
        let httpOperationResponse = new msRest.HttpOperationResponse(request, response);
        httpOperationResponse.body = result;
        if (err) { reject(err); }
        else { resolve(httpOperationResponse); }
        return;
      });
    });
  }

  /**
   * Recognize Text operation. When you use the Recognize Text interface, the
   * response contains a field called 'Operation-Location'. The
   * 'Operation-Location' field contains the URL that you must use for your Get
   * Recognize Text Operation Result operation.
   *
   * @param {object} image An image stream.
   *
   * @param {string} mode Type of text to recognize. Possible values include:
   * 'Handwritten', 'Printed'
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @param {function} [optionalCallback] - The optional callback.
   *
   * @returns {function|Promise} If a callback was passed as the last parameter
   * then it returns the callback else returns a Promise.
   *
   * {Promise} A promise is returned
   *
   *                      @resolve {null} - The deserialized result object.
   *
   *                      @reject {Error} - The error object.
   *
   * {function} optionalCallback(err, result, request, response)
   *
   *                      {Error}  err        - The Error object if an error occurred, null otherwise.
   *
   *                      {null} [result]   - The deserialized result object if an error did not occur.
   *
   *                      {object} [request]  - The HTTP Request object if an error did not occur.
   *
   *                      {stream} [response] - The HTTP Response stream if an error did not occur.
   */
  recognizeTextInStream(image, mode, options, optionalCallback) {
    let client = this;
    let self = this;
    if (!optionalCallback && typeof options === 'function') {
      optionalCallback = options;
      options = null;
    }
    if (!optionalCallback) {
      return new Promise((resolve, reject) => {
        self._recognizeTextInStream(image, mode, options, (err, result, request, response) => {
          if (err) { reject(err); }
          else { resolve(result); }
          return;
        });
      });
    } else {
      return self._recognizeTextInStream(image, mode, options, optionalCallback);
    }
  }

  /**
   * Use this interface to get the result of a Read Document operation, employing
   * the state-of-the-art Optical Character Recognition (OCR) algorithms
   * optimized for text-heavy documents. When you use the Read Document
   * interface, the response contains a field called "Operation-Location". The
   * "Operation-Location" field contains the URL that you must use for your "Get
   * Read Result operation" to access OCR results.​
   *
   * @param {object} image An image stream.
   *
   * @param {string} mode Type of text to recognize. Possible values include:
   * 'Handwritten', 'Printed'
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @returns {Promise} A promise is returned
   *
   * @resolve {HttpOperationResponse<null>} - The deserialized result object.
   *
   * @reject {Error} - The error object.
   */
  batchReadFileInStreamWithHttpOperationResponse(image, mode, options) {
    let client = this;
    let self = this;
    return new Promise((resolve, reject) => {
      self._batchReadFileInStream(image, mode, options, (err, result, request, response) => {
        let httpOperationResponse = new msRest.HttpOperationResponse(request, response);
        httpOperationResponse.body = result;
        if (err) { reject(err); }
        else { resolve(httpOperationResponse); }
        return;
      });
    });
  }

  /**
   * Use this interface to get the result of a Read Document operation, employing
   * the state-of-the-art Optical Character Recognition (OCR) algorithms
   * optimized for text-heavy documents. When you use the Read Document
   * interface, the response contains a field called "Operation-Location". The
   * "Operation-Location" field contains the URL that you must use for your "Get
   * Read Result operation" to access OCR results.​
   *
   * @param {object} image An image stream.
   *
   * @param {string} mode Type of text to recognize. Possible values include:
   * 'Handwritten', 'Printed'
   *
   * @param {object} [options] Optional Parameters.
   *
   * @param {object} [options.customHeaders] Headers that will be added to the
   * request
   *
   * @param {function} [optionalCallback] - The optional callback.
   *
   * @returns {function|Promise} If a callback was passed as the last parameter
   * then it returns the callback else returns a Promise.
   *
   * {Promise} A promise is returned
   *
   *                      @resolve {null} - The deserialized result object.
   *
   *                      @reject {Error} - The error object.
   *
   * {function} optionalCallback(err, result, request, response)
   *
   *                      {Error}  err        - The Error object if an error occurred, null otherwise.
   *
   *                      {null} [result]   - The deserialized result object if an error did not occur.
   *
   *                      {object} [request]  - The HTTP Request object if an error did not occur.
   *
   *                      {stream} [response] - The HTTP Response stream if an error did not occur.
   */
  batchReadFileInStream(image, mode, options, optionalCallback) {
    let client = this;
    let self = this;
    if (!optionalCallback && typeof options === 'function') {
      optionalCallback = options;
      options = null;
    }
    if (!optionalCallback) {
      return new Promise((resolve, reject) => {
        self._batchReadFileInStream(image, mode, options, (err, result, request, response) => {
          if (err) { reject(err); }
          else { resolve(result); }
          return;
        });
      });
    } else {
      return self._batchReadFileInStream(image, mode, options, optionalCallback);
    }
  }

}

module.exports = ComputerVisionClient;
module.exports['default'] = ComputerVisionClient;
module.exports.ComputerVisionClient = ComputerVisionClient;
module.exports.ComputerVisionModels = models;
