module Qeweney::ResponseMethods

def file_full_path(path, opts)

def file_full_path(path, opts)
  if (base_path = opts[:base_path])
    File.join(opts[:base_path], path)
  else
    path
  end
end

def redirect(url, status = Status::FOUND)

def redirect(url, status = Status::FOUND)
  respond(nil, ':status' => status, 'Location' => url)
end

def redirect_to_host(new_host, status = Status::FOUND)

def redirect_to_host(new_host, status = Status::FOUND)
  secure_uri = "//#{new_host}#{uri}"
  redirect(secure_uri, status)
end

def redirect_to_https(status = Status::MOVED_PERMANENTLY)

def redirect_to_https(status = Status::MOVED_PERMANENTLY)
  secure_uri = "https://#{host}#{uri}"
  redirect(secure_uri, status)
end

def respond_with_static_file(path, etag, last_modified, opts)

def respond_with_static_file(path, etag, last_modified, opts)
  cache_headers = {
    'etag' => etag,
    'last-modified' => last_modified,
  }
  File.open(path, 'r') do |f|
    if opts[:headers]
      opts[:headers].merge!(cache_headers)
    else
      opts[:headers] = cache_headers
    end
    # accept_encoding should return encodings in client's order of preference
    accept_encoding.each do |encoding|
      case encoding
      when 'deflate'
        return serve_io_deflate(f, opts)
      when 'gzip'
        return serve_io_gzip(f, opts)
      end
    end
    serve_io(f, opts)
  end
end

def serve_file(path, opts = {})

def serve_file(path, opts = {})
  full_path = file_full_path(path, opts)
  stat = File.stat(full_path)
  etag = StaticFileCaching.file_stat_to_etag(stat)
  last_modified = StaticFileCaching.file_stat_to_last_modified(stat)
  if validate_static_file_cache(etag, last_modified)
    return respond(nil, {
      ':status' => Status::NOT_MODIFIED,
      'etag' => etag
    })
  end
  mime_type = Qeweney::MimeTypes[File.extname(path)]
  opts[:stat] = stat
  (opts[:headers] ||= {})['Content-Type'] ||= mime_type if mime_type
  respond_with_static_file(full_path, etag, last_modified, opts)
rescue Errno::ENOENT
  respond(nil, ':status' => Status::NOT_FOUND)
end

def serve_io(io, opts)

def serve_io(io, opts)
  respond(io.read, opts[:headers] || {})
end

def serve_io_deflate(io, opts)

def serve_io_deflate(io, opts)
  deflate = Zlib::Deflate.new
  headers = opts[:headers].merge(
    'content-encoding' => 'deflate',
    'vary' => 'Accept-Encoding'
  )
  respond(deflate.deflate(io.read, Zlib::FINISH), headers)
end

def serve_io_gzip(io, opts)

def serve_io_gzip(io, opts)
  buf = StringIO.new
  z = Zlib::GzipWriter.new(buf)
  z << io.read
  z.flush
  z.close
  headers = opts[:headers].merge(
    'content-encoding' => 'gzip',
    'vary' => 'Accept-Encoding'
  )
  respond(buf.string, headers)
end

def serve_rack(app)

def serve_rack(app)
  response = app.(Qeweney.rack_env_from_request(self))
  headers = (response[1] || {}).merge(':status' => response[0])
  respond(response[2].join, headers)
  # TODO: send separate chunks for multi-part body
  # TODO: add support for streaming body
  # TODO: add support for websocket
end

def upgrade(protocol, custom_headers = nil)

def upgrade(protocol, custom_headers = nil)
  upgrade_headers = {
    ':status' => Status::SWITCHING_PROTOCOLS,
    'Upgrade' => protocol,
    'Connection' => 'upgrade'
  }
  upgrade_headers.merge!(custom_headers) if custom_headers
  respond(nil, upgrade_headers)
end

def upgrade_to_websocket(custom_headers = nil)

def upgrade_to_websocket(custom_headers = nil)
  key = "#{headers['sec-websocket-key']}#{WEBSOCKET_GUID}"
  upgrade_headers = {
    'Sec-WebSocket-Accept' => Digest::SHA1.base64digest(key)
  }
  upgrade_headers.merge!(custom_headers) if custom_headers
  upgrade('websocket', upgrade_headers)
  adapter.websocket_connection(self)
end

def validate_static_file_cache(etag, last_modified)

def validate_static_file_cache(etag, last_modified)
  if (none_match = headers['if-none-match'])
    return true if none_match == etag
  end
  if (modified_since = headers['if-modified-since'])
    return true if modified_since == last_modified
  end
  false
end