module Queenbee

def self.api_error(message, rcode, rbody, error_obj)

def self.api_error(message, rcode, rbody, error_obj)
  APIError.new(message, nil, rcode, rbody, error_obj)
end

def self.api_url(url="")

def self.api_url(url="")
  @api_base + url
end

def self.authentication_error(message, rcode, rbody, error_obj)

def self.authentication_error(message, rcode, rbody, error_obj)
  AuthenticationError.new(message, nil, rcode, rbody, error_obj)
end

def self.general_api_error(rcode, rbody)

def self.general_api_error(rcode, rbody)
  APIError.new("Invalid response object from API: #{rbody.inspect} " +
               "(HTTP response code was #{rcode})", nil, rcode, rbody)
end

def self.handle_api_error(rcode, rbody)

def self.handle_api_error(rcode, rbody)
  begin
    error_obj = JSON.parse(rbody)
  rescue JSON::ParserError
    raise general_api_error(rcode, rbody)
  end
  case rcode.to_i
  when 400, 404, 422
    raise invalid_request_error("Invalid request", rcode, rbody, error_obj).to_s
  when 401
    raise authentication_error("Unauthorized", rcode, rbody, error_obj).to_s
  when 500
    raise api_error("Server returned an error", rcode, rbody, error_obj).to_s
  else
    raise api_error("An error has occurred", rcode, rbody, error_obj).to_s
  end
end

def self.handle_connection_error(e)

def self.handle_connection_error(e)
  case e
  when SocketError
    message = "Unexpected error when trying to connect to Queenbee."
  when NoMethodError
    message = "Unexpected HTTP response code"
  else
    message = "Unexpected error communicating with Queenbee."
  end
  raise APIConnectionError.new(message + "\n\n(Network error: #{e.message})")
end

def self.invalid_request_error(message, rcode, rbody, error_obj)

def self.invalid_request_error(message, rcode, rbody, error_obj)
  InvalidRequestError.new(message, nil, rcode, rbody, error_obj)
end

def self.request(method, url, token, params={}, headers={})

def self.request(method, url, token, params={}, headers={})
  unless token ||= @token
    raise AuthenticationError.new("No token provided")
  end
  url = api_url(url)
  begin
    uri = URI(url)
    request = Net::HTTP::Get.new(uri) if method == :get
    request = Net::HTTP::Post.new(uri) if method == :post
    request = Net::HTTP::Put.new(uri) if method == :put
    request = Net::HTTP::Delete.new(uri) if method == :delete
    request["User-Agent"] = "Queenbee gem"
    request["Authorization"] = "Token token=\"#{token}\""
    request["Content-Type"] = "application/json"
    request.body = params.to_json
    http = Net::HTTP.new(uri.hostname, uri.port)
    # see http://www.rubyinside.com/how-to-cure-nethttps-risky-default-https-behavior-4010.html
    # for info about ssl verification
    http.use_ssl = true if uri.scheme == "https"
    http.verify_mode = OpenSSL::SSL::VERIFY_NONE if uri.scheme == "https"
    response = http.start { |h| h.request(request) }
    handle_api_error(response.code, response.body) unless (200..299).include?(response.code.to_i)
  rescue SocketError => e
    handle_connection_error(e)
  rescue NoMethodError => e
    handle_connection_error(e)
  rescue OpenSSL::SSL::SSLError => e
    handle_connection_error(e)
  rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH => e
    handle_connection_error(e)
  rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
    Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
    handle_connection_error(e)
  end
  [response, token]
end

def self.retrieve(id, opts={})

def self.retrieve(id, opts={})
  instance = self.new(id, opts)
  instance
end