# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Ruby SDK for convenient access of PredictionIO Output API.
#
# Author::    PredictionIO Team (support@prediction.io)
# Copyright:: Copyright (c) 2014 TappingStone, Inc.
# License::   Apache License, Version 2.0

module PredictionIO
  # This class contains methods that interface with PredictionIO Engine
  # Instances that are trained from PredictionIO built-in Engines.
  #
  # Many REST request methods support optional arguments. They can be supplied
  # to these methods as Hash'es. For a complete reference, please visit
  # http://prediction.io.
  #
  # == Synopsis
  # In most cases, using synchronous methods. If you have a special performance
  # requirement, you may want to take a look at asynchronous methods.
  #
  # === Instantiate an EngineClient
  #     # Include the PredictionIO SDK
  #     require 'predictionio'
  #
  #     client = PredictionIO::EngineClient.new
  #
  # === Send a Query to Retrieve Predictions
  #     # PredictionIO call to record the view action
  #     begin
  #       result = client.query('uid' => 'foobar')
  #     rescue NotFoundError => e
  #       ...
  #     rescue BadRequestError => e
  #       ...
  #     rescue ServerError => e
  #       ...
  #     end
  class EngineClient
    # Raised when an event is not created after a synchronous API call.
    class NotFoundError < StandardError; end

    # Raised when the query is malformed.
    class BadRequestError < StandardError; end

    # Raised when the Engine Instance returns a server error.
    class ServerError < StandardError; end

    # Create a new PredictionIO Event Client with defaults:
    # - 1 concurrent HTTP(S) connections (threads)
    # - API entry point at http://localhost:8000 (apiurl)
    # - a 60-second timeout for each HTTP(S) connection (thread_timeout)
    def initialize(apiurl = 'http://localhost:8000', threads = 1, thread_timeout = 60)
      @http = PredictionIO::Connection.new(URI(apiurl), threads, thread_timeout)
    end

    # Returns the number of pending requests within the current client.
    def pending_requests
      @http.packages.size
    end

    # Returns PredictionIO's status in string.
    def get_status
      status = @http.aget(PredictionIO::AsyncRequest.new('/')).get
      begin
        status.body
      rescue
        status
      end
    end

    # :category: Asynchronous Methods
    # Asynchronously sends a query and returns PredictionIO::AsyncResponse
    # object immediately. The query should be a Ruby data structure that can be
    # converted to a JSON object.
    #
    # Corresponding REST API method: POST /
    #
    # See also #send_query.
    def asend_query(query)
      @http.apost(PredictionIO::AsyncRequest.new('/queries.json', query.to_json))
    end

    # :category: Synchronous Methods
    # Synchronously sends a query and block until predictions are received.
    #
    # See also #asend_query.
    #
    # call-seq:
    # send_query(data)
    # send_query(async_response)
    def send_query(*args)
      sync_events(:asend_query, *args)
    end

    protected

    # Internal helper method. Do not call directly.
    def sync_events(sync_m, *args)
      if args[0].is_a?(PredictionIO::AsyncResponse)
        response = args[0].get
      else
        response = send(sync_m, *args).get
      end
      return JSON.parse(response.body) if response.is_a?(Net::HTTPOK)
      begin
        msg = response.body
      rescue
        raise response
      end
      if response.is_a?(Net::HTTPBadRequest)
        fail BadRequestError, msg
      elsif response.is_a?(Net::HTTPNotFound)
        fail NotFoundError, msg
      elsif response.is_a?(Net::HTTPServerError)
        fail ServerError, msg
      else
        fail msg
      end
    end
  end
end
