{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE FlexibleContexts #-}

module Simplex.Chat.Files where

import Simplex.Chat.Controller
import Simplex.Messaging.Util (ifM)
import System.FilePath (combine, splitExtensions)
import UnliftIO.Directory (doesDirectoryExist, doesFileExist, getHomeDirectory, getTemporaryDirectory)

uniqueCombine :: FilePath -> String -> IO FilePath
uniqueCombine :: FilePath -> FilePath -> IO FilePath
uniqueCombine FilePath
fPath FilePath
fName = Int -> IO FilePath
forall {m :: * -> *} {a}.
(MonadIO m, Eq a, Num a, Show a) =>
a -> m FilePath
tryCombine (Int
0 :: Int)
  where
    tryCombine :: a -> m FilePath
tryCombine a
n =
      let (FilePath
name, FilePath
ext) = FilePath -> (FilePath, FilePath)
splitExtensions FilePath
fName
          suffix :: FilePath
suffix = if a
n a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 then FilePath
"" else FilePath
"_" FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> a -> FilePath
forall a. Show a => a -> FilePath
show a
n
          f :: FilePath
f = FilePath
fPath FilePath -> FilePath -> FilePath
`combine` (FilePath
name FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
suffix FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
ext)
       in m Bool -> m FilePath -> m FilePath -> m FilePath
forall (m :: * -> *) a. Monad m => m Bool -> m a -> m a -> m a
ifM (FilePath -> m Bool
forall (m :: * -> *). MonadIO m => FilePath -> m Bool
doesFileExist FilePath
f) (a -> m FilePath
tryCombine (a -> m FilePath) -> a -> m FilePath
forall a b. (a -> b) -> a -> b
$ a
n a -> a -> a
forall a. Num a => a -> a -> a
+ a
1) (FilePath -> m FilePath
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure FilePath
f)

getChatTempDirectory :: CM' FilePath
getChatTempDirectory :: CM' FilePath
getChatTempDirectory = (ChatController -> TVar (Maybe FilePath)) -> CM' (Maybe FilePath)
forall a. (ChatController -> TVar a) -> CM' a
chatReadVar' ChatController -> TVar (Maybe FilePath)
tempDirectory CM' (Maybe FilePath)
-> (Maybe FilePath -> CM' FilePath) -> CM' FilePath
forall a b.
ReaderT ChatController IO a
-> (a -> ReaderT ChatController IO b)
-> ReaderT ChatController IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= CM' FilePath
-> (FilePath -> CM' FilePath) -> Maybe FilePath -> CM' FilePath
forall b a. b -> (a -> b) -> Maybe a -> b
maybe CM' FilePath
forall (m :: * -> *). MonadIO m => m FilePath
getTemporaryDirectory FilePath -> CM' FilePath
forall a. a -> ReaderT ChatController IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure

getDefaultFilesFolder :: CM' FilePath
getDefaultFilesFolder :: CM' FilePath
getDefaultFilesFolder = do
  FilePath
dir <- (FilePath -> FilePath -> FilePath
`combine` FilePath
"Downloads") (FilePath -> FilePath) -> CM' FilePath -> CM' FilePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> CM' FilePath
forall (m :: * -> *). MonadIO m => m FilePath
getHomeDirectory
  ReaderT ChatController IO Bool
-> CM' FilePath -> CM' FilePath -> CM' FilePath
forall (m :: * -> *) a. Monad m => m Bool -> m a -> m a -> m a
ifM (FilePath -> ReaderT ChatController IO Bool
forall (m :: * -> *). MonadIO m => FilePath -> m Bool
doesDirectoryExist FilePath
dir) (FilePath -> CM' FilePath
forall a. a -> ReaderT ChatController IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure FilePath
dir) CM' FilePath
getChatTempDirectory