{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE LambdaCase #-}
{-|
Module      : Discord.Internal.Voice.CommonUtils
Description : Strictly for internal use only. See Discord.Voice for the public interface.
Copyright   : (c) Yuto Takano (2021)
License     : MIT
Maintainer  : moa17stock@gmail.com

= WARNING

This module is considered __internal__.

The Package Versioning Policy __does not apply__.

The contents of this module may change __in any way whatsoever__ and __without__
__any warning__ between minor versions of this package.

= Description

This module provides useful utility functions used in discord-haskell-voice.
-}
module Discord.Internal.Voice.CommonUtils where

import Control.Concurrent
import Control.Concurrent.Async ( race )
import Lens.Micro
import Data.Text qualified as T
import Data.Time.Clock.POSIX
import Data.Time
import GHC.Weak
import System.Timeout ( timeout )

-- | @tshow@ is a shorthand alias for @T.pack . show@.
tshow :: Show a => a -> T.Text
tshow :: a -> Text
tshow = String -> Text
T.pack (String -> Text) -> (a -> String) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
show

-- | @maybeToRight@ puts the maybe value into the right hand side of the Either,
-- with a default value provided for the Left as the first argument.
maybeToRight :: a -> Maybe b -> Either a b
maybeToRight :: a -> Maybe b -> Either a b
maybeToRight a
a = Either a b -> (b -> Either a b) -> Maybe b -> Either a b
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (a -> Either a b
forall a b. a -> Either a b
Left a
a) b -> Either a b
forall a b. b -> Either a b
Right

-- | @timeoutMs@ performs an IO action for a maximum of @millisec@ milliseconds.
timeoutMs :: Int -> IO a -> IO (Maybe a)
timeoutMs :: Int -> IO a -> IO (Maybe a)
timeoutMs Int
millisec = Int -> IO a -> IO (Maybe a)
forall a. Int -> IO a -> IO (Maybe a)
timeout (Int
millisec Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10Int -> Int -> Int
forall a b. (Num a, Integral b) => a -> b -> a
^(Int
3 :: Int))

-- | @killWkThread@ kills a thread referenced by Weak ThreadId. If the thread is
-- no longer alive (that is, if @deRefWeak@ is Nothing), this function will do
-- nothing.
killWkThread :: Weak ThreadId -> IO ()
killWkThread :: Weak ThreadId -> IO ()
killWkThread Weak ThreadId
tid = Weak ThreadId -> IO (Maybe ThreadId)
forall v. Weak v -> IO (Maybe v)
deRefWeak Weak ThreadId
tid IO (Maybe ThreadId) -> (Maybe ThreadId -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    Maybe ThreadId
Nothing -> () -> IO ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
    Just ThreadId
x  -> ThreadId -> IO ()
killThread ThreadId
x