/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * license agreements; and to You under the Apache License, version 2.0:
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * This file is part of the Apache Pekko project, which was derived from Akka.
 */

/*
 * Copyright (C) 2009-2022 Lightbend Inc. <https://www.lightbend.com>
 */

package docs.http.scaladsl

import org.apache.pekko
//#import-model
import org.apache.pekko.http.scaladsl.model._
//#import-model

import pekko.testkit.PekkoSpec
import pekko.util.ByteString
import pekko.http.scaladsl.model.headers.BasicHttpCredentials

class ModelSpec extends PekkoSpec {
  "construct request" in {
    // #construct-request
    import HttpMethods._

    // construct a simple GET request to `homeUri`
    val homeUri = Uri("/abc")
    HttpRequest(GET, uri = homeUri)

    // construct simple GET request to "/index" (implicit string to Uri conversion)
    HttpRequest(GET, uri = "/index")

    // construct simple POST request containing entity
    val data = ByteString("abc")
    HttpRequest(POST, uri = "/receive", entity = data)

    // customize every detail of HTTP request
    import HttpProtocols._
    import MediaTypes._
    import HttpCharsets._
    val userData = ByteString("abc")
    val authorization = headers.Authorization(BasicHttpCredentials("user", "pass"))
    HttpRequest(
      PUT,
      uri = "/user",
      entity = HttpEntity(`text/plain`.withCharset(`UTF-8`), userData),
      headers = List(authorization),
      protocol = `HTTP/1.0`)
    // #construct-request
  }

  "construct response" in {
    // #construct-response
    import StatusCodes._

    // simple OK response without data created using the integer status code
    HttpResponse(200)

    // 404 response created using the named StatusCode constant
    HttpResponse(NotFound)

    // 404 response with a body explaining the error
    HttpResponse(404, entity = "Unfortunately, the resource couldn't be found.")

    // A redirecting response containing an extra header
    val locationHeader = headers.Location("http://example.com/other")
    HttpResponse(Found, headers = List(locationHeader))

    // #construct-response
  }

  "deal with headers" in {
    // #headers
    import org.apache.pekko.http.scaladsl.model.headers._

    // create a ``Location`` header
    val loc = Location("http://example.com/other")

    // create an ``Authorization`` header with HTTP Basic authentication data
    val auth = Authorization(BasicHttpCredentials("joe", "josepp"))

    // custom type
    case class User(name: String, pass: String)

    // a method that extracts basic HTTP credentials from a request
    def credentialsOfRequest(req: HttpRequest): Option[User] =
      for {
        case Authorization(BasicHttpCredentials(user, pass)) <- req.header[Authorization]
      } yield User(user, pass)
    // #headers

    credentialsOfRequest(HttpRequest(headers = List(auth))) should be(Some(User("joe", "josepp")))
    credentialsOfRequest(HttpRequest()) should be(None)
    credentialsOfRequest(HttpRequest(headers = List(Authorization(GenericHttpCredentials("Other",
      Map.empty[String, String]))))) should be(None)
  }

  "deal with attributes" in {
    // #attributes
    case class User(name: String)
    object User {
      val attributeKey = AttributeKey[User]("user")
    }

    def determineUser(req: HttpRequest): HttpRequest = {
      val user = // ... somehow determine the user for this request
        // #attributes
        User("joe")
      // #attributes

      // Add the attribute
      req.addAttribute(User.attributeKey, user)
    }
    // #attributes

    val requestWithAttribute = determineUser(HttpRequest())
    // #attributes

    // Retrieve the attribute
    val user: Option[User] = requestWithAttribute.attribute(User.attributeKey)
    // #attributes
    user should be(Some(User("joe")))
  }

  "Synthetic-header-s3" in {
    // #synthetic-header-s3
    import org.apache.pekko.http.scaladsl.model.headers.`Raw-Request-URI`
    val req = HttpRequest(uri = "/ignored", headers = List(`Raw-Request-URI`("/a/b%2Bc")))
    // #synthetic-header-s3
  }
}
