Skip to content
Snippets Groups Projects
Daily.scala 3.45 KiB
Newer Older
package models

import repositories.DailyRepository
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{Future, Await}
import scala.concurrent.duration._
import org.bson.types.ObjectId
import java.util.Date
import java.time.Instant
import java.text.SimpleDateFormat

Felipe D'Abrantes's avatar
Felipe D'Abrantes committed
import play.api.libs.json.{Json, JsValue, JsString, JsObject, JsArray}

case class Daily(
    id: Option[ObjectId],
    userId: ObjectId,
    questionId: ObjectId,
    content: String,
    usersLiked: Seq[ObjectId],
    createdAt: Date,
    updatedAt: Date

object Daily {
    val dailyRepo = new DailyRepository()

    def createDailyAsync(
        userId: ObjectId,
        questionId: ObjectId,
        content: String,
        timeout: Int = 4
    ): Daily = {
        val now: Date = Date.from(Instant.now())
        val daily: Daily = Daily(None, userId, questionId, content, Seq.empty[ObjectId], now, now)
        val future: Future[Daily] = dailyRepo.insertDaily(daily)
        Await.result(future, timeout.seconds)
    }

    def getAllDailiesAsync(timeout: Int = 4): Seq[Daily] = {
        val future: Future[Seq[Daily]] = dailyRepo.getAllDailies()
        Await.result(future, timeout.seconds)
    }

    def getUserDailiesAsync(userId: ObjectId, timeout: Int = 4): Seq[Daily] = {
        val future: Future[Seq[Daily]] = dailyRepo.getUserDailies(userId)
        Await.result(future, timeout.seconds)
    }

    def getUserFeedAsync(userId: ObjectId, timeout: Int = 4): Seq[Daily] = {
        // Sequentially waits for Future objects to complete before calling next method
        val result: Future[Seq[Daily]] = for {
            friends: Seq[ObjectId] <- User.getUserFriends(userId)
            feed: Seq[Daily] <- dailyRepo.getUserDailies(friends)
        } yield feed

        Await.result(result, timeout.seconds)
    }

    def likeAsync(dailyId: ObjectId, userId: ObjectId, timeout: Int = 4): Unit = {
        val result: Future[Unit] = for {
            daily: Daily <- dailyRepo.getDaily(dailyId)
            unit: Unit <- dailyRepo.like(daily, userId)
        } yield unit

        Await.result(result, timeout.seconds)
    }

    // Convert from Daily object to JSON (serializing to JSON)
    def toJson(daily: Daily): JsValue = {
        val usersLikedAsJsStrings = daily.usersLiked.map(id => JsString(id.toString()))

        val dateFormat: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
        val formattedCreatedAt: String = dateFormat.format(daily.createdAt)
        val formattedUpdatedAt: String = dateFormat.format(daily.updatedAt)
        val dailyJson = Seq(
            "id" -> JsString(daily.id.getOrElse("").toString()),
            "userId" -> JsString(daily.userId.toString()),
            "questionId" -> JsString(daily.questionId.toString()),
            "content" -> JsString(daily.content),
            "usersLiked" -> JsArray(usersLikedAsJsStrings),
            "createdAt" -> JsString(formattedCreatedAt),
            "updatedAt" -> JsString(formattedUpdatedAt)
        )
        
        Json.toJson(JsObject(dailyJson))
    // Convert from Daily set to JSON (serializing to JSON)
    def toJson(dailies: Seq[Daily]): JsValue = {
        val dailiesJson = dailies.map(daily => Daily.toJson(daily))

        Json.toJson(JsArray(dailiesJson))

    def toString(daily: Daily): String =
        return s"Daily(${daily.id.toString()}, ${daily.userId.toString()}, ${daily.questionId.toString()}, ${daily.content}, ${daily.usersLiked.toString()})"