package industries.sunshine.planningpoker import cats.effect._ import cats.syntax.all._ import org.http4s._, org.http4s.dsl.io._, org.http4s.implicits._ import org.http4s.websocket.WebSocketFrame // import io.circe.generic.auto._ import io.circe.syntax._ import org.http4s.circe.CirceEntityDecoder._ import scala.concurrent.duration._ import org.http4s.server.websocket.WebSocketBuilder import fs2._ import industries.sunshine.planningpoker.common.Models.RoomID import industries.sunshine.planningpoker.common.Models.PlayerID import org.http4s.server.AuthMiddleware.apply import org.http4s.server.AuthMiddleware object MyHttpService { def create(auth: Auth)( wsb: WebSocketBuilder[cats.effect.IO] ): HttpApp[cats.effect.IO] = { val authedRoomRoutes: AuthedRoutes[(PlayerID, RoomID), IO] = AuthedRoutes.of { case GET -> Root / "subscribe" as (playerId, roomId) => { val send: Stream[IO, WebSocketFrame] = Stream .emits(TestModels.testChangesList) .covary[IO].metered(1.second).map(state => WebSocketFrame.Text(state.asJson.noSpaces)) val receive: Pipe[IO, WebSocketFrame, Unit] = _.evalMap { case WebSocketFrame.Text(text, _) => Sync[IO].delay(println(text)) case other => Sync[IO].delay(println(other)) } wsb.build(send, receive) } case GET -> Root / "vote" / vote as (playerId, roomId) => { // TODO forward these to the service implementation IO(println(s">> got $vote from $playerId in $roomId")) >> Ok() } case GET -> Root / "end-voting" as (playerId, roomId) => { IO(println(s">> got request to end voting from $playerId in $roomId")) >> Ok() } case GET -> Root / "new-poll" as (playerId, roomId) => { IO(println(s">> got request to start new voting from $playerId in $roomId")) >> Ok() } } val authMiddleware = AuthMiddleware(auth.authUser) val aa = authMiddleware(authedRoomRoutes) val authenticationRoute = HttpRoutes .of[IO] { case req @ POST -> Root / "login" => { for { data <- req.as[Requests.LogIn] authResult <- auth.accessRoom( data.roomName, data.password, data.nickname ) resp <- authResult match { case Left(error) => Forbidden(error) case Right(sessionId) => { Ok("Logged in!").map( _.addCookie( ResponseCookie("authcookie", sessionId.toString()) ) ) } } } yield resp } } (authenticationRoute <+> authMiddleware(authedRoomRoutes)).orNotFound } }