{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
module Tweeter.Db (
    findById
  , insert
  , insert'
  , newTweetId
  , list
  , TweetDb
  , init
  ) where

import           Control.Concurrent.MVar
import           Control.Monad.IO.Class
import qualified Data.List as DL
import qualified Data.Map as M
import           Data.UUID
import           Data.UUID.V4
import           P
import           System.IO
import           Tweeter.Data

-- MVar backed hashmap of tweet id's to tweets
type TweetDb = MVar (M.Map TweetId Tweet)

init :: IO TweetDb
init = do
  s <- newMVar M.empty
  pure s

findById :: TweetDb -> TweetId -> IO (Maybe Tweet)
findById t id' = modifyMVar t $ \m ->
  pure (m, M.lookup id' m)

insert :: TweetDb -> Tweet -> IO TweetId
insert t t' = do
  uuid <- newTweetId
  insert' t uuid t'

insert' :: TweetDb -> TweetId -> Tweet -> IO TweetId
insert' db id' t' = do
  modifyMVar_ db $ \m ->
    pure $ M.insert id' t' m
  pure id'

list :: TweetDb -> IO [KeyedTweet]
list t = modifyMVar t $ \m ->
  pure (m, DL.sort . fmap (\(x,y) -> KeyedTweet x y) $ (M.assocs m))

newTweetId :: IO TweetId
newTweetId = liftIO nextRandom >>= return . TweetId . toText
