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[IO])( 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.joinRoom( data.roomName, data.password, data.nickname, data.nickPassword) resp <- authResult match { case Left(error) => Forbidden(error) case Right(authCookie) => { IO(println(s"> logging in ${data.nickname} to ${data.roomName}")) >> Ok().map(_.addCookie(authCookie)) } } } yield resp } } (authenticationRoute <+> authMiddleware(authedRoomRoutes)).orNotFound } }