require 'multi_json'

module TicketingHub
  module Request

    def delete path, options={}
      request(:delete, path, options).body
    end

    def get path, options={}
      response = request(:get, path, options)
      body = response.body

      if auto_traversal && body.is_a?(Array)
        while next_url = links(response)['next']
          response = request(:get, next_url, options)
          body += response.body
        end
      end

      body
    end

    def patch path, options={}
      request(:patch, path, options).body
    end

    def post path, options={}
      request(:post, path, options).body
    end

    def put path, options={}
      request(:put, path, options).body
    end

    private

      # Executes the request, checking if it was successful
      #
      # @return [Boolean] True on success, false otherwise
      def boolean_from_response(method, path, options={})
       request(method, path, options).status == 204
      rescue TicketingHub::NotFound
        false
      end

      def request(method, path, options={})
        force_urlencoded = options.delete(:force_urlencoded) || false
        url = options.delete(:endpoint) || api_endpoint
        conn_options = { force_urlencoded: force_urlencoded, url: url }

        connection(conn_options).send(method) do |request|
          case method
          when :get, :delete, :head
            request.url(path, options)
          when :patch, :post, :put
            request.path = path
            unless options.empty?
              request.body = force_urlencoded ? options : MultiJson.dump(options)
            end
          end

          if TicketingHub.request_host
            request.headers['Host'] = TicketingHub.request_host
          end
        end
      end

      def links(response)
        links = ( response.headers["Link"] || "" ).split(', ').map do |link|
          url, type = link.match(/<(.*?)>; rel="(\w+)"/).captures
          [ type, url ]
        end

        Hash[ *links.flatten ]
      end
    end
end