# frozen_string_literal: true

# Copyright 2018 IBM All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# IBM Watson™ Compare and Comply analyzes governing documents to provide details
# about critical aspects of the documents.

require "concurrent"
require "erb"
require "json"
require "ibm_cloud_sdk_core"
require_relative "./common.rb"

# Module for the Watson APIs
module IBMWatson
  ##
  # The Compare Comply V1 service.
  class CompareComplyV1 < IBMCloudSdkCore::BaseService
    include Concurrent::Async
    ##
    # @!method initialize(args)
    # Construct a new client for the Compare Comply service.
    #
    # @param args [Hash] The args to initialize with
    # @option args version [String] The API version date to use with the service, in
    #   "YYYY-MM-DD" format. Whenever the API is changed in a backwards
    #   incompatible way, a new minor version of the API is released.
    #   The service uses the API version for the date you specify, or
    #   the most recent version before that date. Note that you should
    #   not programmatically specify the current date at runtime, in
    #   case the API has been updated since your application's release.
    #   Instead, specify a version date that is compatible with your
    #   application, and don't change it until your application is
    #   ready for a later version.
    # @option args url [String] The base url to use when contacting the service (e.g.
    #   "https://gateway.watsonplatform.net/compare-comply/api").
    #   The base url may differ between Bluemix regions.
    # @option args iam_apikey [String] An API key that can be used to request IAM tokens. If
    #   this API key is provided, the SDK will manage the token and handle the
    #   refreshing.
    # @option args iam_access_token [String] An IAM access token is fully managed by the application.
    #   Responsibility falls on the application to refresh the token, either before
    #   it expires or reactively upon receiving a 401 from the service as any requests
    #   made with an expired token will fail.
    # @option args iam_url [String] An optional URL for the IAM service API. Defaults to
    #   'https://iam.ng.bluemix.net/identity/token'.
    def initialize(args = {})
      @__async_initialized__ = false
      defaults = {}
      defaults[:version] = nil
      defaults[:url] = "https://gateway.watsonplatform.net/compare-comply/api"
      defaults[:iam_apikey] = nil
      defaults[:iam_access_token] = nil
      defaults[:iam_url] = nil
      args = defaults.merge(args)
      args[:vcap_services_name] = "compare-comply"
      super
      @version = args[:version]
      args[:display_name] = "Compare Comply"
    end

    #########################
    # HTML conversion
    #########################

    ##
    # @!method convert_to_html(file:, filename: nil, file_content_type: nil, model: nil)
    # Convert document to HTML.
    # Converts a document to HTML.
    # @param file [File] The document to convert.
    # @param filename [String] The filename for file.
    # @param file_content_type [String] The content type of file.
    # @param model [String] The analysis model to be used by the service. For the **Element classification**
    #   and **Compare two documents** methods, the default is `contracts`. For the
    #   **Extract tables** method, the default is `tables`. These defaults apply to the
    #   standalone methods as well as to the methods' use in batch-processing requests.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def convert_to_html(file:, filename: nil, file_content_type: nil, model: nil)
      raise ArgumentError.new("file must be provided") if file.nil?

      headers = {
      }
      sdk_headers = Common.new.get_sdk_headers("compare-comply", "V1", "convert_to_html")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version,
        "model" => model
      }

      form_data = {}

      unless file.instance_of?(StringIO) || file.instance_of?(File)
        file = file.respond_to?(:to_json) ? StringIO.new(file.to_json) : StringIO.new(file)
      end
      filename = file.path if filename.nil? && file.respond_to?(:path)
      form_data[:file] = HTTP::FormData::File.new(file, content_type: file_content_type.nil? ? "application/octet-stream" : file_content_type, filename: filename)

      method_url = "/v1/html_conversion"

      response = request(
        method: "POST",
        url: method_url,
        headers: headers,
        params: params,
        form: form_data,
        accept_json: true
      )
      response
    end
    #########################
    # Element classification
    #########################

    ##
    # @!method classify_elements(file:, file_content_type: nil, model: nil)
    # Classify the elements of a document.
    # Analyzes the structural and semantic elements of a document.
    # @param file [File] The document to classify.
    # @param file_content_type [String] The content type of file.
    # @param model [String] The analysis model to be used by the service. For the **Element classification**
    #   and **Compare two documents** methods, the default is `contracts`. For the
    #   **Extract tables** method, the default is `tables`. These defaults apply to the
    #   standalone methods as well as to the methods' use in batch-processing requests.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def classify_elements(file:, file_content_type: nil, model: nil)
      raise ArgumentError.new("file must be provided") if file.nil?

      headers = {
      }
      sdk_headers = Common.new.get_sdk_headers("compare-comply", "V1", "classify_elements")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version,
        "model" => model
      }

      form_data = {}

      unless file.instance_of?(StringIO) || file.instance_of?(File)
        file = file.respond_to?(:to_json) ? StringIO.new(file.to_json) : StringIO.new(file)
      end
      form_data[:file] = HTTP::FormData::File.new(file, content_type: file_content_type.nil? ? "application/octet-stream" : file_content_type, filename: file.respond_to?(:path) ? file.path : nil)

      method_url = "/v1/element_classification"

      response = request(
        method: "POST",
        url: method_url,
        headers: headers,
        params: params,
        form: form_data,
        accept_json: true
      )
      response
    end
    #########################
    # Tables
    #########################

    ##
    # @!method extract_tables(file:, file_content_type: nil, model: nil)
    # Extract a document's tables.
    # Analyzes the tables in a document.
    # @param file [File] The document on which to run table extraction.
    # @param file_content_type [String] The content type of file.
    # @param model [String] The analysis model to be used by the service. For the **Element classification**
    #   and **Compare two documents** methods, the default is `contracts`. For the
    #   **Extract tables** method, the default is `tables`. These defaults apply to the
    #   standalone methods as well as to the methods' use in batch-processing requests.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def extract_tables(file:, file_content_type: nil, model: nil)
      raise ArgumentError.new("file must be provided") if file.nil?

      headers = {
      }
      sdk_headers = Common.new.get_sdk_headers("compare-comply", "V1", "extract_tables")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version,
        "model" => model
      }

      form_data = {}

      unless file.instance_of?(StringIO) || file.instance_of?(File)
        file = file.respond_to?(:to_json) ? StringIO.new(file.to_json) : StringIO.new(file)
      end
      form_data[:file] = HTTP::FormData::File.new(file, content_type: file_content_type.nil? ? "application/octet-stream" : file_content_type, filename: file.respond_to?(:path) ? file.path : nil)

      method_url = "/v1/tables"

      response = request(
        method: "POST",
        url: method_url,
        headers: headers,
        params: params,
        form: form_data,
        accept_json: true
      )
      response
    end
    #########################
    # Comparison
    #########################

    ##
    # @!method compare_documents(file_1:, file_2:, file_1_content_type: nil, file_2_content_type: nil, file_1_label: nil, file_2_label: nil, model: nil)
    # Compare two documents.
    # Compares two input documents. Documents must be in the same format.
    # @param file_1 [File] The first document to compare.
    # @param file_2 [File] The second document to compare.
    # @param file_1_content_type [String] The content type of file_1.
    # @param file_2_content_type [String] The content type of file_2.
    # @param file_1_label [String] A text label for the first document.
    # @param file_2_label [String] A text label for the second document.
    # @param model [String] The analysis model to be used by the service. For the **Element classification**
    #   and **Compare two documents** methods, the default is `contracts`. For the
    #   **Extract tables** method, the default is `tables`. These defaults apply to the
    #   standalone methods as well as to the methods' use in batch-processing requests.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def compare_documents(file_1:, file_2:, file_1_content_type: nil, file_2_content_type: nil, file_1_label: nil, file_2_label: nil, model: nil)
      raise ArgumentError.new("file_1 must be provided") if file_1.nil?

      raise ArgumentError.new("file_2 must be provided") if file_2.nil?

      headers = {
      }
      sdk_headers = Common.new.get_sdk_headers("compare-comply", "V1", "compare_documents")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version,
        "file_1_label" => file_1_label,
        "file_2_label" => file_2_label,
        "model" => model
      }

      form_data = {}

      unless file_1.instance_of?(StringIO) || file_1.instance_of?(File)
        file_1 = file_1.respond_to?(:to_json) ? StringIO.new(file_1.to_json) : StringIO.new(file_1)
      end
      form_data[:file_1] = HTTP::FormData::File.new(file_1, content_type: file_1_content_type.nil? ? "application/octet-stream" : file_1_content_type, filename: file_1.respond_to?(:path) ? file_1.path : nil)

      unless file_2.instance_of?(StringIO) || file_2.instance_of?(File)
        file_2 = file_2.respond_to?(:to_json) ? StringIO.new(file_2.to_json) : StringIO.new(file_2)
      end
      form_data[:file_2] = HTTP::FormData::File.new(file_2, content_type: file_2_content_type.nil? ? "application/octet-stream" : file_2_content_type, filename: file_2.respond_to?(:path) ? file_2.path : nil)

      method_url = "/v1/comparison"

      response = request(
        method: "POST",
        url: method_url,
        headers: headers,
        params: params,
        form: form_data,
        accept_json: true
      )
      response
    end
    #########################
    # Feedback
    #########################

    ##
    # @!method add_feedback(feedback_data:, user_id: nil, comment: nil)
    # Add feedback.
    # Adds feedback in the form of _labels_ from a subject-matter expert (SME) to a
    #   governing document.
    #   **Important:** Feedback is not immediately incorporated into the training model,
    #   nor is it guaranteed to be incorporated at a later date. Instead, submitted
    #   feedback is used to suggest future updates to the training model.
    # @param feedback_data [FeedbackDataInput] Feedback data for submission.
    # @param user_id [String] An optional string identifying the user.
    # @param comment [String] An optional comment on or description of the feedback.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def add_feedback(feedback_data:, user_id: nil, comment: nil)
      raise ArgumentError.new("feedback_data must be provided") if feedback_data.nil?

      headers = {
      }
      sdk_headers = Common.new.get_sdk_headers("compare-comply", "V1", "add_feedback")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version
      }

      data = {
        "feedback_data" => feedback_data,
        "user_id" => user_id,
        "comment" => comment
      }

      method_url = "/v1/feedback"

      response = request(
        method: "POST",
        url: method_url,
        headers: headers,
        params: params,
        json: data,
        accept_json: true
      )
      response
    end

    ##
    # @!method delete_feedback(feedback_id:, model: nil)
    # Delete a specified feedback entry.
    # Deletes a feedback entry with a specified `feedback_id`.
    # @param feedback_id [String] A string that specifies the feedback entry to be deleted from the document.
    # @param model [String] The analysis model to be used by the service. For the **Element classification**
    #   and **Compare two documents** methods, the default is `contracts`. For the
    #   **Extract tables** method, the default is `tables`. These defaults apply to the
    #   standalone methods as well as to the methods' use in batch-processing requests.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def delete_feedback(feedback_id:, model: nil)
      raise ArgumentError.new("feedback_id must be provided") if feedback_id.nil?

      headers = {
      }
      sdk_headers = Common.new.get_sdk_headers("compare-comply", "V1", "delete_feedback")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version,
        "model" => model
      }

      method_url = "/v1/feedback/%s" % [ERB::Util.url_encode(feedback_id)]

      response = request(
        method: "DELETE",
        url: method_url,
        headers: headers,
        params: params,
        accept_json: true
      )
      response
    end

    ##
    # @!method get_feedback(feedback_id:, model: nil)
    # List a specified feedback entry.
    # Lists a feedback entry with a specified `feedback_id`.
    # @param feedback_id [String] A string that specifies the feedback entry to be included in the output.
    # @param model [String] The analysis model to be used by the service. For the **Element classification**
    #   and **Compare two documents** methods, the default is `contracts`. For the
    #   **Extract tables** method, the default is `tables`. These defaults apply to the
    #   standalone methods as well as to the methods' use in batch-processing requests.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def get_feedback(feedback_id:, model: nil)
      raise ArgumentError.new("feedback_id must be provided") if feedback_id.nil?

      headers = {
      }
      sdk_headers = Common.new.get_sdk_headers("compare-comply", "V1", "get_feedback")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version,
        "model" => model
      }

      method_url = "/v1/feedback/%s" % [ERB::Util.url_encode(feedback_id)]

      response = request(
        method: "GET",
        url: method_url,
        headers: headers,
        params: params,
        accept_json: true
      )
      response
    end

    ##
    # @!method list_feedback(feedback_type: nil, before: nil, after: nil, document_title: nil, model_id: nil, model_version: nil, category_removed: nil, category_added: nil, category_not_changed: nil, type_removed: nil, type_added: nil, type_not_changed: nil, page_limit: nil, cursor: nil, sort: nil, include_total: nil)
    # List the feedback in a document.
    # Lists the feedback in a document.
    # @param feedback_type [String] An optional string that filters the output to include only feedback with the
    #   specified feedback type. The only permitted value is `element_classification`.
    # @param before [Time] An optional string in the format `YYYY-MM-DD` that filters the output to include
    #   only feedback that was added before the specified date.
    # @param after [Time] An optional string in the format `YYYY-MM-DD` that filters the output to include
    #   only feedback that was added after the specified date.
    # @param document_title [String] An optional string that filters the output to include only feedback from the
    #   document with the specified `document_title`.
    # @param model_id [String] An optional string that filters the output to include only feedback with the
    #   specified `model_id`. The only permitted value is `contracts`.
    # @param model_version [String] An optional string that filters the output to include only feedback with the
    #   specified `model_version`.
    # @param category_removed [String] An optional string in the form of a comma-separated list of categories. If this is
    #   specified, the service filters the output to include only feedback that has at
    #   least one category from the list removed.
    # @param category_added [String] An optional string in the form of a comma-separated list of categories. If this is
    #   specified, the service filters the output to include only feedback that has at
    #   least one category from the list added.
    # @param category_not_changed [String] An optional string in the form of a comma-separated list of categories. If this is
    #   specified, the service filters the output to include only feedback that has at
    #   least one category from the list unchanged.
    # @param type_removed [String] An optional string of comma-separated `nature`:`party` pairs. If this is
    #   specified, the service filters the output to include only feedback that has at
    #   least one `nature`:`party` pair from the list removed.
    # @param type_added [String] An optional string of comma-separated `nature`:`party` pairs. If this is
    #   specified, the service filters the output to include only feedback that has at
    #   least one `nature`:`party` pair from the list removed.
    # @param type_not_changed [String] An optional string of comma-separated `nature`:`party` pairs. If this is
    #   specified, the service filters the output to include only feedback that has at
    #   least one `nature`:`party` pair from the list unchanged.
    # @param page_limit [Fixnum] An optional integer specifying the number of documents that you want the service
    #   to return.
    # @param cursor [String] An optional string that returns the set of documents after the previous set. Use
    #   this parameter with the `page_limit` parameter.
    # @param sort [String] An optional comma-separated list of fields in the document to sort on. You can
    #   optionally specify the sort direction by prefixing the value of the field with `-`
    #   for descending order or `+` for ascending order (the default). Currently permitted
    #   sorting fields are `created`, `user_id`, and `document_title`.
    # @param include_total [Boolean] An optional boolean value. If specified as `true`, the `pagination` object in the
    #   output includes a value called `total` that gives the total count of feedback
    #   created.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def list_feedback(feedback_type: nil, before: nil, after: nil, document_title: nil, model_id: nil, model_version: nil, category_removed: nil, category_added: nil, category_not_changed: nil, type_removed: nil, type_added: nil, type_not_changed: nil, page_limit: nil, cursor: nil, sort: nil, include_total: nil)
      headers = {
      }
      sdk_headers = Common.new.get_sdk_headers("compare-comply", "V1", "list_feedback")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version,
        "feedback_type" => feedback_type,
        "before" => before,
        "after" => after,
        "document_title" => document_title,
        "model_id" => model_id,
        "model_version" => model_version,
        "category_removed" => category_removed,
        "category_added" => category_added,
        "category_not_changed" => category_not_changed,
        "type_removed" => type_removed,
        "type_added" => type_added,
        "type_not_changed" => type_not_changed,
        "page_limit" => page_limit,
        "cursor" => cursor,
        "sort" => sort,
        "include_total" => include_total
      }

      method_url = "/v1/feedback"

      response = request(
        method: "GET",
        url: method_url,
        headers: headers,
        params: params,
        accept_json: true
      )
      response
    end
    #########################
    # Batches
    #########################

    ##
    # @!method create_batch(function:, input_credentials_file:, input_bucket_location:, input_bucket_name:, output_credentials_file:, output_bucket_location:, output_bucket_name:, model: nil)
    # Submit a batch-processing request.
    # Run Compare and Comply methods over a collection of input documents.
    #   **Important:** Batch processing requires the use of the [IBM Cloud Object Storage
    #   service](https://cloud.ibm.com/docs/services/cloud-object-storage/about-cos.html#about-ibm-cloud-object-storage).
    #   The use of IBM Cloud Object Storage with Compare and Comply is discussed at [Using
    #   batch
    #   processing](https://cloud.ibm.com/docs/services/compare-comply/batching.html#before-you-batch).
    # @param function [String] The Compare and Comply method to run across the submitted input documents.
    # @param input_credentials_file [File] A JSON file containing the input Cloud Object Storage credentials. At a minimum,
    #   the credentials must enable `READ` permissions on the bucket defined by the
    #   `input_bucket_name` parameter.
    # @param input_bucket_location [String] The geographical location of the Cloud Object Storage input bucket as listed on
    #   the **Endpoint** tab of your Cloud Object Storage instance; for example, `us-geo`,
    #   `eu-geo`, or `ap-geo`.
    # @param input_bucket_name [String] The name of the Cloud Object Storage input bucket.
    # @param output_credentials_file [File] A JSON file that lists the Cloud Object Storage output credentials. At a minimum,
    #   the credentials must enable `READ` and `WRITE` permissions on the bucket defined
    #   by the `output_bucket_name` parameter.
    # @param output_bucket_location [String] The geographical location of the Cloud Object Storage output bucket as listed on
    #   the **Endpoint** tab of your Cloud Object Storage instance; for example, `us-geo`,
    #   `eu-geo`, or `ap-geo`.
    # @param output_bucket_name [String] The name of the Cloud Object Storage output bucket.
    # @param model [String] The analysis model to be used by the service. For the **Element classification**
    #   and **Compare two documents** methods, the default is `contracts`. For the
    #   **Extract tables** method, the default is `tables`. These defaults apply to the
    #   standalone methods as well as to the methods' use in batch-processing requests.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def create_batch(function:, input_credentials_file:, input_bucket_location:, input_bucket_name:, output_credentials_file:, output_bucket_location:, output_bucket_name:, model: nil)
      raise ArgumentError.new("function must be provided") if function.nil?

      raise ArgumentError.new("input_credentials_file must be provided") if input_credentials_file.nil?

      raise ArgumentError.new("input_bucket_location must be provided") if input_bucket_location.nil?

      raise ArgumentError.new("input_bucket_name must be provided") if input_bucket_name.nil?

      raise ArgumentError.new("output_credentials_file must be provided") if output_credentials_file.nil?

      raise ArgumentError.new("output_bucket_location must be provided") if output_bucket_location.nil?

      raise ArgumentError.new("output_bucket_name must be provided") if output_bucket_name.nil?

      headers = {
      }
      sdk_headers = Common.new.get_sdk_headers("compare-comply", "V1", "create_batch")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version,
        "function" => function,
        "model" => model
      }

      form_data = {}

      unless input_credentials_file.instance_of?(StringIO) || input_credentials_file.instance_of?(File)
        input_credentials_file = input_credentials_file.respond_to?(:to_json) ? StringIO.new(input_credentials_file.to_json) : StringIO.new(input_credentials_file)
      end
      form_data[:input_credentials_file] = HTTP::FormData::File.new(input_credentials_file, content_type: "application/json", filename: input_credentials_file.respond_to?(:path) ? input_credentials_file.path : nil)

      form_data[:input_bucket_location] = HTTP::FormData::Part.new(input_bucket_location.to_s, content_type: "text/plain")

      form_data[:input_bucket_name] = HTTP::FormData::Part.new(input_bucket_name.to_s, content_type: "text/plain")

      unless output_credentials_file.instance_of?(StringIO) || output_credentials_file.instance_of?(File)
        output_credentials_file = output_credentials_file.respond_to?(:to_json) ? StringIO.new(output_credentials_file.to_json) : StringIO.new(output_credentials_file)
      end
      form_data[:output_credentials_file] = HTTP::FormData::File.new(output_credentials_file, content_type: "application/json", filename: output_credentials_file.respond_to?(:path) ? output_credentials_file.path : nil)

      form_data[:output_bucket_location] = HTTP::FormData::Part.new(output_bucket_location.to_s, content_type: "text/plain")

      form_data[:output_bucket_name] = HTTP::FormData::Part.new(output_bucket_name.to_s, content_type: "text/plain")

      method_url = "/v1/batches"

      response = request(
        method: "POST",
        url: method_url,
        headers: headers,
        params: params,
        form: form_data,
        accept_json: true
      )
      response
    end

    ##
    # @!method get_batch(batch_id:)
    # Get information about a specific batch-processing job.
    # Gets information about a batch-processing job with a specified ID.
    # @param batch_id [String] The ID of the batch-processing job whose information you want to retrieve.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def get_batch(batch_id:)
      raise ArgumentError.new("batch_id must be provided") if batch_id.nil?

      headers = {
      }
      sdk_headers = Common.new.get_sdk_headers("compare-comply", "V1", "get_batch")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version
      }

      method_url = "/v1/batches/%s" % [ERB::Util.url_encode(batch_id)]

      response = request(
        method: "GET",
        url: method_url,
        headers: headers,
        params: params,
        accept_json: true
      )
      response
    end

    ##
    # @!method list_batches
    # List submitted batch-processing jobs.
    # Lists batch-processing jobs submitted by users.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def list_batches
      headers = {
      }
      sdk_headers = Common.new.get_sdk_headers("compare-comply", "V1", "list_batches")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version
      }

      method_url = "/v1/batches"

      response = request(
        method: "GET",
        url: method_url,
        headers: headers,
        params: params,
        accept_json: true
      )
      response
    end

    ##
    # @!method update_batch(batch_id:, action:, model: nil)
    # Update a pending or active batch-processing job.
    # Updates a pending or active batch-processing job. You can rescan the input bucket
    #   to check for new documents or cancel a job.
    # @param batch_id [String] The ID of the batch-processing job you want to update.
    # @param action [String] The action you want to perform on the specified batch-processing job.
    # @param model [String] The analysis model to be used by the service. For the **Element classification**
    #   and **Compare two documents** methods, the default is `contracts`. For the
    #   **Extract tables** method, the default is `tables`. These defaults apply to the
    #   standalone methods as well as to the methods' use in batch-processing requests.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def update_batch(batch_id:, action:, model: nil)
      raise ArgumentError.new("batch_id must be provided") if batch_id.nil?

      raise ArgumentError.new("action must be provided") if action.nil?

      headers = {
      }
      sdk_headers = Common.new.get_sdk_headers("compare-comply", "V1", "update_batch")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version,
        "action" => action,
        "model" => model
      }

      method_url = "/v1/batches/%s" % [ERB::Util.url_encode(batch_id)]

      response = request(
        method: "PUT",
        url: method_url,
        headers: headers,
        params: params,
        accept_json: true
      )
      response
    end
  end
end


# frozen_string_literal: true

# Copyright 2018 IBM All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# The IBM Watson™ Tone Analyzer service uses linguistic analysis to detect
# emotional and language tones in written text. The service can analyze tone at both the
# document and sentence levels. You can use the service to understand how your written
# communications are perceived and then to improve the tone of your communications.
# Businesses can use the service to learn the tone of their customers' communications and
# to respond to each customer appropriately, or to understand and improve their customer
# conversations.
#
# **Note:** Request logging is disabled for the Tone Analyzer service. Regardless of
# whether you set the `X-Watson-Learning-Opt-Out` request header, the service does not log
# or retain data from requests and responses.

require "concurrent"
require "erb"
require "json"
require "ibm_cloud_sdk_core"
require_relative "./common.rb"

# Module for the Watson APIs
module IBMWatson
  ##
  # The Tone Analyzer V3 service.
  class ToneAnalyzerV3 < IBMCloudSdkCore::BaseService
    include Concurrent::Async
    ##
    # @!method initialize(args)
    # Construct a new client for the Tone Analyzer service.
    #
    # @param args [Hash] The args to initialize with
    # @option args version [String] The API version date to use with the service, in
    #   "YYYY-MM-DD" format. Whenever the API is changed in a backwards
    #   incompatible way, a new minor version of the API is released.
    #   The service uses the API version for the date you specify, or
    #   the most recent version before that date. Note that you should
    #   not programmatically specify the current date at runtime, in
    #   case the API has been updated since your application's release.
    #   Instead, specify a version date that is compatible with your
    #   application, and don't change it until your application is
    #   ready for a later version.
    # @option args url [String] The base url to use when contacting the service (e.g.
    #   "https://gateway.watsonplatform.net/tone-analyzer/api").
    #   The base url may differ between Bluemix regions.
    # @option args username [String] The username used to authenticate with the service.
    #   Username and password credentials are only required to run your
    #   application locally or outside of Bluemix. When running on
    #   Bluemix, the credentials will be automatically loaded from the
    #   `VCAP_SERVICES` environment variable.
    # @option args password [String] The password used to authenticate with the service.
    #   Username and password credentials are only required to run your
    #   application locally or outside of Bluemix. When running on
    #   Bluemix, the credentials will be automatically loaded from the
    #   `VCAP_SERVICES` environment variable.
    # @option args iam_apikey [String] An API key that can be used to request IAM tokens. If
    #   this API key is provided, the SDK will manage the token and handle the
    #   refreshing.
    # @option args iam_access_token [String] An IAM access token is fully managed by the application.
    #   Responsibility falls on the application to refresh the token, either before
    #   it expires or reactively upon receiving a 401 from the service as any requests
    #   made with an expired token will fail.
    # @option args iam_url [String] An optional URL for the IAM service API. Defaults to
    #   'https://iam.ng.bluemix.net/identity/token'.
    def initialize(args = {})
      @__async_initialized__ = false
      defaults = {}
      defaults[:version] = nil
      defaults[:url] = "https://gateway.watsonplatform.net/tone-analyzer/api"
      defaults[:username] = nil
      defaults[:password] = nil
      defaults[:iam_apikey] = nil
      defaults[:iam_access_token] = nil
      defaults[:iam_url] = nil
      args = defaults.merge(args)
      args[:vcap_services_name] = "tone_analyzer"
      super
      @version = args[:version]
      args[:display_name] = "Tone Analyzer"
    end

    #########################
    # Methods
    #########################

    ##
    # @!method tone(tone_input:, sentences: nil, tones: nil, content_language: nil, accept_language: nil, content_type: nil)
    # Analyze general tone.
    # Use the general purpose endpoint to analyze the tone of your input content. The
    #   service analyzes the content for emotional and language tones. The method always
    #   analyzes the tone of the full document; by default, it also analyzes the tone of
    #   each individual sentence of the content.
    #
    #   You can submit no more than 128 KB of total input content and no more than 1000
    #   individual sentences in JSON, plain text, or HTML format. The service analyzes the
    #   first 1000 sentences for document-level analysis and only the first 100 sentences
    #   for sentence-level analysis.
    #
    #   Per the JSON specification, the default character encoding for JSON content is
    #   effectively always UTF-8; per the HTTP specification, the default encoding for
    #   plain text and HTML is ISO-8859-1 (effectively, the ASCII character set). When
    #   specifying a content type of plain text or HTML, include the `charset` parameter
    #   to indicate the character encoding of the input text; for example: `Content-Type:
    #   text/plain;charset=utf-8`. For `text/html`, the service removes HTML tags and
    #   analyzes only the textual content.
    #
    #   **See also:** [Using the general-purpose
    #   endpoint](https://cloud.ibm.com/docs/services/tone-analyzer/using-tone.html#using-the-general-purpose-endpoint).
    # @param tone_input [ToneInput] JSON, plain text, or HTML input that contains the content to be analyzed. For JSON
    #   input, provide an object of type `ToneInput`.
    # @param sentences [Boolean] Indicates whether the service is to return an analysis of each individual sentence
    #   in addition to its analysis of the full document. If `true` (the default), the
    #   service returns results for each sentence.
    # @param tones [Array[String]] **`2017-09-21`:** Deprecated. The service continues to accept the parameter for
    #   backward-compatibility, but the parameter no longer affects the response.
    #
    #   **`2016-05-19`:** A comma-separated list of tones for which the service is to
    #   return its analysis of the input; the indicated tones apply both to the full
    #   document and to individual sentences of the document. You can specify one or more
    #   of the valid values. Omit the parameter to request results for all three tones.
    # @param content_language [String] The language of the input text for the request: English or French. Regional
    #   variants are treated as their parent language; for example, `en-US` is interpreted
    #   as `en`. The input content must match the specified language. Do not submit
    #   content that contains both languages. You can use different languages for
    #   **Content-Language** and **Accept-Language**.
    #   * **`2017-09-21`:** Accepts `en` or `fr`.
    #   * **`2016-05-19`:** Accepts only `en`.
    # @param accept_language [String] The desired language of the response. For two-character arguments, regional
    #   variants are treated as their parent language; for example, `en-US` is interpreted
    #   as `en`. You can use different languages for **Content-Language** and
    #   **Accept-Language**.
    # @param content_type [String] The type of the input. A character encoding can be specified by including a
    #   `charset` parameter. For example, 'text/plain;charset=utf-8'.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def tone(tone_input:, sentences: nil, tones: nil, content_language: nil, accept_language: nil, content_type: nil)
      raise ArgumentError.new("tone_input must be provided") if tone_input.nil?

      headers = {
        "Content-Language" => content_language,
        "Accept-Language" => accept_language,
        "Content-Type" => content_type
      }
      sdk_headers = Common.new.get_sdk_headers("tone_analyzer", "V3", "tone")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version,
        "sentences" => sentences,
        "tones" => tones.to_a
      }

      if content_type.start_with?("application/json") && tone_input.instance_of?(Hash)
        data = tone_input.to_json
      else
        data = tone_input
      end

      method_url = "/v3/tone"

      response = request(
        method: "POST",
        url: method_url,
        headers: headers,
        params: params,
        data: data,
        accept_json: true
      )
      response
    end

    ##
    # @!method tone_chat(utterances:, content_language: nil, accept_language: nil)
    # Analyze customer engagement tone.
    # Use the customer engagement endpoint to analyze the tone of customer service and
    #   customer support conversations. For each utterance of a conversation, the method
    #   reports the most prevalent subset of the following seven tones: sad, frustrated,
    #   satisfied, excited, polite, impolite, and sympathetic.
    #
    #   If you submit more than 50 utterances, the service returns a warning for the
    #   overall content and analyzes only the first 50 utterances. If you submit a single
    #   utterance that contains more than 500 characters, the service returns an error for
    #   that utterance and does not analyze the utterance. The request fails if all
    #   utterances have more than 500 characters. Per the JSON specification, the default
    #   character encoding for JSON content is effectively always UTF-8.
    #
    #   **See also:** [Using the customer-engagement
    #   endpoint](https://cloud.ibm.com/docs/services/tone-analyzer/using-tone-chat.html#using-the-customer-engagement-endpoint).
    # @param utterances [Array[Utterance]] An array of `Utterance` objects that provides the input content that the service
    #   is to analyze.
    # @param content_language [String] The language of the input text for the request: English or French. Regional
    #   variants are treated as their parent language; for example, `en-US` is interpreted
    #   as `en`. The input content must match the specified language. Do not submit
    #   content that contains both languages. You can use different languages for
    #   **Content-Language** and **Accept-Language**.
    #   * **`2017-09-21`:** Accepts `en` or `fr`.
    #   * **`2016-05-19`:** Accepts only `en`.
    # @param accept_language [String] The desired language of the response. For two-character arguments, regional
    #   variants are treated as their parent language; for example, `en-US` is interpreted
    #   as `en`. You can use different languages for **Content-Language** and
    #   **Accept-Language**.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def tone_chat(utterances:, content_language: nil, accept_language: nil)
      raise ArgumentError.new("utterances must be provided") if utterances.nil?

      headers = {
        "Content-Language" => content_language,
        "Accept-Language" => accept_language
      }
      sdk_headers = Common.new.get_sdk_headers("tone_analyzer", "V3", "tone_chat")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version
      }

      data = {
        "utterances" => utterances
      }

      method_url = "/v3/tone_chat"

      response = request(
        method: "POST",
        url: method_url,
        headers: headers,
        params: params,
        json: data,
        accept_json: true
      )
      response
    end
  end
end


# frozen_string_literal: true

# Copyright 2018 IBM All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# IBM Watson™ Language Translator translates text from one language to another.
# The service offers multiple IBM provided translation models that you can customize based
# on your unique terminology and language. Use Language Translator to take news from
# across the globe and present it in your language, communicate with your customers in
# their own language, and more.

require "concurrent"
require "erb"
require "json"
require "ibm_cloud_sdk_core"
require_relative "./common.rb"

# Module for the Watson APIs
module IBMWatson
  ##
  # The Language Translator V3 service.
  class LanguageTranslatorV3 < IBMCloudSdkCore::BaseService
    include Concurrent::Async
    ##
    # @!method initialize(args)
    # Construct a new client for the Language Translator service.
    #
    # @param args [Hash] The args to initialize with
    # @option args version [String] The API version date to use with the service, in
    #   "YYYY-MM-DD" format. Whenever the API is changed in a backwards
    #   incompatible way, a new minor version of the API is released.
    #   The service uses the API version for the date you specify, or
    #   the most recent version before that date. Note that you should
    #   not programmatically specify the current date at runtime, in
    #   case the API has been updated since your application's release.
    #   Instead, specify a version date that is compatible with your
    #   application, and don't change it until your application is
    #   ready for a later version.
    # @option args url [String] The base url to use when contacting the service (e.g.
    #   "https://gateway.watsonplatform.net/language-translator/api").
    #   The base url may differ between Bluemix regions.
    # @option args username [String] The username used to authenticate with the service.
    #   Username and password credentials are only required to run your
    #   application locally or outside of Bluemix. When running on
    #   Bluemix, the credentials will be automatically loaded from the
    #   `VCAP_SERVICES` environment variable.
    # @option args password [String] The password used to authenticate with the service.
    #   Username and password credentials are only required to run your
    #   application locally or outside of Bluemix. When running on
    #   Bluemix, the credentials will be automatically loaded from the
    #   `VCAP_SERVICES` environment variable.
    # @option args iam_apikey [String] An API key that can be used to request IAM tokens. If
    #   this API key is provided, the SDK will manage the token and handle the
    #   refreshing.
    # @option args iam_access_token [String] An IAM access token is fully managed by the application.
    #   Responsibility falls on the application to refresh the token, either before
    #   it expires or reactively upon receiving a 401 from the service as any requests
    #   made with an expired token will fail.
    # @option args iam_url [String] An optional URL for the IAM service API. Defaults to
    #   'https://iam.ng.bluemix.net/identity/token'.
    def initialize(args = {})
      @__async_initialized__ = false
      defaults = {}
      defaults[:version] = nil
      defaults[:url] = "https://gateway.watsonplatform.net/language-translator/api"
      defaults[:username] = nil
      defaults[:password] = nil
      defaults[:iam_apikey] = nil
      defaults[:iam_access_token] = nil
      defaults[:iam_url] = nil
      args = defaults.merge(args)
      args[:vcap_services_name] = "language_translator"
      super
      @version = args[:version]
      args[:display_name] = "Language Translator"
    end

    #########################
    # Translation
    #########################

    ##
    # @!method translate(text:, model_id: nil, source: nil, target: nil)
    # Translate.
    # Translates the input text from the source language to the target language.
    # @param text [Array[String]] Input text in UTF-8 encoding. Multiple entries will result in multiple
    #   translations in the response.
    # @param model_id [String] A globally unique string that identifies the underlying model that is used for
    #   translation.
    # @param source [String] Translation source language code.
    # @param target [String] Translation target language code.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def translate(text:, model_id: nil, source: nil, target: nil)
      raise ArgumentError.new("text must be provided") if text.nil?

      headers = {
      }
      sdk_headers = Common.new.get_sdk_headers("language_translator", "V3", "translate")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version
      }

      data = {
        "text" => text,
        "model_id" => model_id,
        "source" => source,
        "target" => target
      }

      method_url = "/v3/translate"

      response = request(
        method: "POST",
        url: method_url,
        headers: headers,
        params: params,
        json: data,
        accept_json: true
      )
      response
    end
    #########################
    # Identification
    #########################

    ##
    # @!method identify(text:)
    # Identify language.
    # Identifies the language of the input text.
    # @param text [String] Input text in UTF-8 format.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def identify(text:)
      raise ArgumentError.new("text must be provided") if text.nil?

      headers = {
      }
      sdk_headers = Common.new.get_sdk_headers("language_translator", "V3", "identify")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version
      }

      data = text
      headers["Content-Type"] = "text/plain"

      method_url = "/v3/identify"

      response = request(
        method: "POST",
        url: method_url,
        headers: headers,
        params: params,
        data: data,
        accept_json: true
      )
      response
    end

    ##
    # @!method list_identifiable_languages
    # List identifiable languages.
    # Lists the languages that the service can identify. Returns the language code (for
    #   example, `en` for English or `es` for Spanish) and name of each language.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def list_identifiable_languages
      headers = {
      }
      sdk_headers = Common.new.get_sdk_headers("language_translator", "V3", "list_identifiable_languages")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version
      }

      method_url = "/v3/identifiable_languages"

      response = request(
        method: "GET",
        url: method_url,
        headers: headers,
        params: params,
        accept_json: true
      )
      response
    end
    #########################
    # Models
    #########################

    ##
    # @!method create_model(base_model_id:, forced_glossary: nil, parallel_corpus: nil, name: nil)
    # Create model.
    # Uploads Translation Memory eXchange (TMX) files to customize a translation model.
    #
    #   You can either customize a model with a forced glossary or with a corpus that
    #   contains parallel sentences. To create a model that is customized with a parallel
    #   corpus and a forced glossary, proceed in two steps: customize with a
    #   parallel corpus first and then customize the resulting model with a glossary.
    #   Depending on the type of customization and the size of the uploaded corpora,
    #   training can range from minutes for a glossary to several hours for a large
    #   parallel corpus. You can upload a single forced glossary file and this file must
    #   be less than 10 MB. You can upload multiple parallel corpora tmx files. The
    #   cumulative file size of all uploaded files is limited to 250 MB. To
    #   successfully train with a parallel corpus you must have at least 5,000 parallel
    #   sentences in your corpus.
    #
    #   You can have a maxium of 10 custom models per language pair.
    # @param base_model_id [String] The model ID of the model to use as the base for customization. To see available
    #   models, use the `List models` method. Usually all IBM provided models are
    #   customizable. In addition, all your models that have been created via parallel
    #   corpus customization, can be further customized with a forced glossary.
    # @param forced_glossary [File] A TMX file with your customizations. The customizations in the file completely
    #   overwrite the domain translaton data, including high frequency or high confidence
    #   phrase translations. You can upload only one glossary with a file size less than
    #   10 MB per call. A forced glossary should contain single words or short phrases.
    # @param parallel_corpus [File] A TMX file with parallel sentences for source and target language. You can upload
    #   multiple parallel_corpus files in one request. All uploaded parallel_corpus files
    #   combined, your parallel corpus must contain at least 5,000 parallel sentences to
    #   train successfully.
    # @param name [String] An optional model name that you can use to identify the model. Valid characters
    #   are letters, numbers, dashes, underscores, spaces and apostrophes. The maximum
    #   length is 32 characters.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def create_model(base_model_id:, forced_glossary: nil, parallel_corpus: nil, name: nil)
      raise ArgumentError.new("base_model_id must be provided") if base_model_id.nil?

      headers = {
      }
      sdk_headers = Common.new.get_sdk_headers("language_translator", "V3", "create_model")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version,
        "base_model_id" => base_model_id,
        "name" => name
      }

      form_data = {}

      unless forced_glossary.nil?
        unless forced_glossary.instance_of?(StringIO) || forced_glossary.instance_of?(File)
          forced_glossary = forced_glossary.respond_to?(:to_json) ? StringIO.new(forced_glossary.to_json) : StringIO.new(forced_glossary)
        end
        form_data[:forced_glossary] = HTTP::FormData::File.new(forced_glossary, content_type: "application/octet-stream", filename: forced_glossary.respond_to?(:path) ? forced_glossary.path : nil)
      end

      unless parallel_corpus.nil?
        unless parallel_corpus.instance_of?(StringIO) || parallel_corpus.instance_of?(File)
          parallel_corpus = parallel_corpus.respond_to?(:to_json) ? StringIO.new(parallel_corpus.to_json) : StringIO.new(parallel_corpus)
        end
        form_data[:parallel_corpus] = HTTP::FormData::File.new(parallel_corpus, content_type: "application/octet-stream", filename: parallel_corpus.respond_to?(:path) ? parallel_corpus.path : nil)
      end

      method_url = "/v3/models"

      response = request(
        method: "POST",
        url: method_url,
        headers: headers,
        params: params,
        form: form_data,
        accept_json: true
      )
      response
    end

    ##
    # @!method delete_model(model_id:)
    # Delete model.
    # Deletes a custom translation model.
    # @param model_id [String] Model ID of the model to delete.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def delete_model(model_id:)
      raise ArgumentError.new("model_id must be provided") if model_id.nil?

      headers = {
      }
      sdk_headers = Common.new.get_sdk_headers("language_translator", "V3", "delete_model")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version
      }

      method_url = "/v3/models/%s" % [ERB::Util.url_encode(model_id)]

      response = request(
        method: "DELETE",
        url: method_url,
        headers: headers,
        params: params,
        accept_json: true
      )
      response
    end

    ##
    # @!method get_model(model_id:)
    # Get model details.
    # Gets information about a translation model, including training status for custom
    #   models. Use this API call to poll the status of your customization request. A
    #   successfully completed training will have a status of `available`.
    # @param model_id [String] Model ID of the model to get.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def get_model(model_id:)
      raise ArgumentError.new("model_id must be provided") if model_id.nil?

      headers = {
      }
      sdk_headers = Common.new.get_sdk_headers("language_translator", "V3", "get_model")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version
      }

      method_url = "/v3/models/%s" % [ERB::Util.url_encode(model_id)]

      response = request(
        method: "GET",
        url: method_url,
        headers: headers,
        params: params,
        accept_json: true
      )
      response
    end

    ##
    # @!method list_models(source: nil, target: nil, default_models: nil)
    # List models.
    # Lists available translation models.
    # @param source [String] Specify a language code to filter results by source language.
    # @param target [String] Specify a language code to filter results by target language.
    # @param default_models [Boolean] If the default parameter isn't specified, the service will return all models
    #   (default and non-default) for each language pair. To return only default models,
    #   set this to `true`. To return only non-default models, set this to `false`. There
    #   is exactly one default model per language pair, the IBM provided base model.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def list_models(source: nil, target: nil, default_models: nil)
      headers = {
      }
      sdk_headers = Common.new.get_sdk_headers("language_translator", "V3", "list_models")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version,
        "source" => source,
        "target" => target,
        "default" => default_models
      }

      method_url = "/v3/models"

      response = request(
        method: "GET",
        url: method_url,
        headers: headers,
        params: params,
        accept_json: true
      )
      response
    end
  end
end


# frozen_string_literal: true

# Copyright 2018 IBM All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Analyze various features of text content at scale. Provide text, raw HTML, or a public
# URL and IBM Watson Natural Language Understanding will give you results for the features
# you request. The service cleans HTML content before analysis by default, so the results
# can ignore most advertisements and other unwanted content.
#
# You can create [custom
# models](https://cloud.ibm.com/docs/services/natural-language-understanding/customizing.html)
# with Watson Knowledge Studio to detect custom entities, relations, and categories in
# Natural Language Understanding.

require "concurrent"
require "erb"
require "json"
require "ibm_cloud_sdk_core"
require_relative "./common.rb"

# Module for the Watson APIs
module IBMWatson
  ##
  # The Natural Language Understanding V1 service.
  class NaturalLanguageUnderstandingV1 < IBMCloudSdkCore::BaseService
    include Concurrent::Async
    ##
    # @!method initialize(args)
    # Construct a new client for the Natural Language Understanding service.
    #
    # @param args [Hash] The args to initialize with
    # @option args version [String] The API version date to use with the service, in
    #   "YYYY-MM-DD" format. Whenever the API is changed in a backwards
    #   incompatible way, a new minor version of the API is released.
    #   The service uses the API version for the date you specify, or
    #   the most recent version before that date. Note that you should
    #   not programmatically specify the current date at runtime, in
    #   case the API has been updated since your application's release.
    #   Instead, specify a version date that is compatible with your
    #   application, and don't change it until your application is
    #   ready for a later version.
    # @option args url [String] The base url to use when contacting the service (e.g.
    #   "https://gateway.watsonplatform.net/natural-language-understanding/api").
    #   The base url may differ between Bluemix regions.
    # @option args username [String] The username used to authenticate with the service.
    #   Username and password credentials are only required to run your
    #   application locally or outside of Bluemix. When running on
    #   Bluemix, the credentials will be automatically loaded from the
    #   `VCAP_SERVICES` environment variable.
    # @option args password [String] The password used to authenticate with the service.
    #   Username and password credentials are only required to run your
    #   application locally or outside of Bluemix. When running on
    #   Bluemix, the credentials will be automatically loaded from the
    #   `VCAP_SERVICES` environment variable.
    # @option args iam_apikey [String] An API key that can be used to request IAM tokens. If
    #   this API key is provided, the SDK will manage the token and handle the
    #   refreshing.
    # @option args iam_access_token [String] An IAM access token is fully managed by the application.
    #   Responsibility falls on the application to refresh the token, either before
    #   it expires or reactively upon receiving a 401 from the service as any requests
    #   made with an expired token will fail.
    # @option args iam_url [String] An optional URL for the IAM service API. Defaults to
    #   'https://iam.ng.bluemix.net/identity/token'.
    def initialize(args = {})
      @__async_initialized__ = false
      defaults = {}
      defaults[:version] = nil
      defaults[:url] = "https://gateway.watsonplatform.net/natural-language-understanding/api"
      defaults[:username] = nil
      defaults[:password] = nil
      defaults[:iam_apikey] = nil
      defaults[:iam_access_token] = nil
      defaults[:iam_url] = nil
      args = defaults.merge(args)
      args[:vcap_services_name] = "natural-language-understanding"
      super
      @version = args[:version]
      args[:display_name] = "Natural Language Understanding"
    end

    #########################
    # Analyze
    #########################

    ##
    # @!method analyze(features:, text: nil, html: nil, url: nil, clean: nil, xpath: nil, fallback_to_raw: nil, return_analyzed_text: nil, language: nil, limit_text_characters: nil)
    # Analyze text.
    # Analyzes text, HTML, or a public webpage for the following features:
    #   - Categories
    #   - Concepts
    #   - Emotion
    #   - Entities
    #   - Keywords
    #   - Metadata
    #   - Relations
    #   - Semantic roles
    #   - Sentiment
    #   - Syntax (Experimental).
    # @param features [Features] Specific features to analyze the document for.
    # @param text [String] The plain text to analyze. One of the `text`, `html`, or `url` parameters is
    #   required.
    # @param html [String] The HTML file to analyze. One of the `text`, `html`, or `url` parameters is
    #   required.
    # @param url [String] The webpage to analyze. One of the `text`, `html`, or `url` parameters is
    #   required.
    # @param clean [Boolean] Set this to `false` to disable webpage cleaning. To learn more about webpage
    #   cleaning, see the [Analyzing
    #   webpages](https://cloud.ibm.com/docs/services/natural-language-understanding/analyzing-webpages.html)
    #   documentation.
    # @param xpath [String] An [XPath
    #   query](https://cloud.ibm.com/docs/services/natural-language-understanding/analyzing-webpages.html#xpath)
    #   to perform on `html` or `url` input. Results of the query will be appended to the
    #   cleaned webpage text before it is analyzed. To analyze only the results of the
    #   XPath query, set the `clean` parameter to `false`.
    # @param fallback_to_raw [Boolean] Whether to use raw HTML content if text cleaning fails.
    # @param return_analyzed_text [Boolean] Whether or not to return the analyzed text.
    # @param language [String] ISO 639-1 code that specifies the language of your text. This overrides automatic
    #   language detection. Language support differs depending on the features you include
    #   in your analysis. See [Language
    #   support](https://www.bluemix.net/docs/services/natural-language-understanding/language-support.html)
    #   for more information.
    # @param limit_text_characters [Fixnum] Sets the maximum number of characters that are processed by the service.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def analyze(features:, text: nil, html: nil, url: nil, clean: nil, xpath: nil, fallback_to_raw: nil, return_analyzed_text: nil, language: nil, limit_text_characters: nil)
      raise ArgumentError.new("features must be provided") if features.nil?

      headers = {
      }
      sdk_headers = Common.new.get_sdk_headers("natural-language-understanding", "V1", "analyze")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version
      }

      data = {
        "features" => features,
        "text" => text,
        "html" => html,
        "url" => url,
        "clean" => clean,
        "xpath" => xpath,
        "fallback_to_raw" => fallback_to_raw,
        "return_analyzed_text" => return_analyzed_text,
        "language" => language,
        "limit_text_characters" => limit_text_characters
      }

      method_url = "/v1/analyze"

      response = request(
        method: "POST",
        url: method_url,
        headers: headers,
        params: params,
        json: data,
        accept_json: true
      )
      response
    end
    #########################
    # Manage models
    #########################

    ##
    # @!method delete_model(model_id:)
    # Delete model.
    # Deletes a custom model.
    # @param model_id [String] Model ID of the model to delete.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def delete_model(model_id:)
      raise ArgumentError.new("model_id must be provided") if model_id.nil?

      headers = {
      }
      sdk_headers = Common.new.get_sdk_headers("natural-language-understanding", "V1", "delete_model")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version
      }

      method_url = "/v1/models/%s" % [ERB::Util.url_encode(model_id)]

      response = request(
        method: "DELETE",
        url: method_url,
        headers: headers,
        params: params,
        accept_json: true
      )
      response
    end

    ##
    # @!method list_models
    # List models.
    # Lists Watson Knowledge Studio [custom
    #   models](https://cloud.ibm.com/docs/services/natural-language-understanding/customizing.html)
    #   that are deployed to your Natural Language Understanding service.
    # @return [IBMCloudSdkCore::DetailedResponse] A `IBMCloudSdkCore::DetailedResponse` object representing the response.
    def list_models
      headers = {
      }
      sdk_headers = Common.new.get_sdk_headers("natural-language-understanding", "V1", "list_models")
      headers.merge!(sdk_headers)

      params = {
        "version" => @version
      }

      method_url = "/v1/models"

      response = request(
        method: "GET",
        url: method_url,
        headers: headers,
        params: params,
        accept_json: true
      )
      response
    end
  end
end