"""
Collection of utilities for working with Requests data
"""
module Requests

using Genie, Genie.Router, Genie.Input
using HTTP

export jsonpayload, rawpayload, filespayload, postpayload, getpayload, getrequest, infilespayload, download, filename, payload


"""
    jsonpayload() :: Dict{String,Any}

Processes an `application/json` `POST` request attempting to convert the payload into a `Dict`.
If it fails to successfully parse the `JSON` data this returns `nothing`. The original payload can still be accessed invoking `rawpayload()`
"""
@inline function jsonpayload() :: Dict{String,Any}
  @params(Genie.PARAMS_JSON_PAYLOAD)
end


"""
    rawpayload() :: String

Returns the raw `POST` payload as a `String`.
"""
@inline function rawpayload() :: String
  @params(Genie.PARAMS_RAW_PAYLOAD)
end


"""
    filespayload() :: Dict{String,HttpFile}

Collection of form uploaded files.
"""
@inline function filespayload() :: Dict{String,HttpFile}
  @params(Genie.PARAMS_FILES)
end


"""
    filespayload(filename::Union{String,Symbol}) :: HttpFile

Returns the `HttpFile` uploaded through the `key` input name.
"""
@inline function filespayload(key::Union{String,Symbol}) :: HttpFile
  @params(Genie.PARAMS_FILES)[string(key)]
end


"""
    infilespayload(key::Union{String,Symbol}) :: Bool

Checks if the collection of uploaded files contains a file stored under the `key` name.
"""
@inline function infilespayload(key::Union{String,Symbol}) :: Bool
  haskey(filespayload(), string(key))
end


"""
    Base.download(file::HttpFile, name::String = file.name)

Saves uploaded `HttpFile` `file` to local storage under the `name` filename.
"""
@inline function Base.download(file::HttpFile, name::String = file.name) :: Int
  write(name, IOBuffer(file.data))
end


"""
    filename(file::HttpFile) :: String

Original filename of the uploaded `HttpFile` `file`.
"""
@inline function filename(file::HttpFile) :: String
  file.name
end


"""
    postpayload() :: Dict{Symbol,Any}

A dict representing the POST variables payload of the request (corresponding to a `form-data` request)
"""
@inline function postpayload() :: Dict{Symbol,Any}
  @params(Genie.PARAMS_POST_KEY)
end


"""
    postpayload(key::Symbol) :: Any

Returns the value of the POST variables `key`.
"""
@inline function postpayload(key::Symbol)
  postpayload()[key]
end


"""
    getpayload(key::Symbol, default::Any)

Returns the value of the POST variables `key` or the `default` value if `key` is not defined.
"""
@inline function postpayload(key::Symbol, default::Any)
  haskey(postpayload(), key) ? postpayload(key) : default
end


"""
    getpayload() :: Dict{Symbol,Any}

A dict representing the GET/query variables payload of the request (the part correspoding to `?foo=bar&baz=moo`)
"""
@inline function getpayload() :: Dict{Symbol,Any}
  @params(Genie.PARAMS_GET_KEY)
end


"""
    getpayload(key::Symbol) :: Any

The value of the GET/query variable `key`, as in `?key=value`
"""
@inline function getpayload(key::Symbol) :: Any
  getpayload()[key]
end


"""
    getpayload(key::Symbol, default::Any) :: Any

The value of the GET/query variable `key`, as in `?key=value`. If `key` is not defined, `default` is returned.
"""
@inline function getpayload(key::Symbol, default::Any) :: Any
  haskey(getpayload(), key) ? getpayload(key) : default
end


"""
    getrequest() :: HTTP.Request

Returns the raw HTTP.Request object associated with the request.
"""
@inline function getrequest() :: HTTP.Request
  @params(Genie.PARAMS_REQUEST_KEY)
end


"""
    payload() :: Any

Utility function for accessing the `@params` collection, which holds the request variables.
"""
@inline function payload() :: Any
  @params
end


"""
    payload(key::Symbol) :: Any

Utility function for accessing the `key` value within the `@params` collection of request variables.
"""
@inline function payload(key::Symbol) :: Any
  @params()[key]
end

end