{-# LANGUAGE TupleSections #-}

module Input.Download(downloadInput, DownloadInput(..)) where

import System.FilePath
import Control.Monad.Extra
import System.Directory
import Data.Conduit.Binary (sinkFile)
import qualified Network.HTTP.Conduit as C
import Network.Connection
import qualified Data.Conduit as C
import General.Util
import General.Timing
import Control.Monad.Trans.Resource
import Control.Exception.Extra

data DownloadInput =
    AlwaysDownloadInput
    | NeverDownloadInput
    | DownloadInputIfNotThere


-- | Download all the input files to input/
downloadInput :: Timing -> Bool -> DownloadInput -> FilePath -> String -> URL -> IO FilePath
downloadInput :: Timing
-> Bool
-> DownloadInput
-> FilePath
-> FilePath
-> FilePath
-> IO FilePath
downloadInput Timing
timing Bool
insecure DownloadInput
download FilePath
dir FilePath
name FilePath
url = do
    let file :: FilePath
file = FilePath
dir FilePath -> FilePath -> FilePath
</> FilePath
"input-" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
name
    exists <- FilePath -> IO Bool
doesFileExist FilePath
file
    let act =
            Timing -> FilePath -> IO () -> IO ()
forall (m :: * -> *) a.
MonadIO m =>
Timing -> FilePath -> m a -> m a
timed Timing
timing (FilePath
"Downloading " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
url) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
                Bool -> FilePath -> FilePath -> IO ()
downloadFile Bool
insecure (FilePath
file FilePath -> FilePath -> FilePath
<.> FilePath
"part") FilePath
url
                FilePath -> FilePath -> IO ()
renameFile (FilePath
file FilePath -> FilePath -> FilePath
<.> FilePath
"part") FilePath
file
    case download of
        DownloadInput
NeverDownloadInput ->
            Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
exists (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
              FilePath -> IO ()
forall a. Partial => FilePath -> IO a
errorIO (FilePath -> IO ()) -> FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"File is not already downloaded and --download=no given, downloading " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
url FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
" to " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
file
        DownloadInput
AlwaysDownloadInput -> IO ()
act
        DownloadInput
DownloadInputIfNotThere ->
            Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
exists IO ()
act
    pure file

downloadFile :: Bool -> FilePath -> String -> IO ()
downloadFile :: Bool -> FilePath -> FilePath -> IO ()
downloadFile Bool
insecure FilePath
file FilePath
url = do
    let request :: Request
request = FilePath -> Request
C.parseRequest_ FilePath
url
    manager <- ManagerSettings -> IO Manager
C.newManager (ManagerSettings -> IO Manager) -> ManagerSettings -> IO Manager
forall a b. (a -> b) -> a -> b
$ TLSSettings -> Maybe SockSettings -> ManagerSettings
C.mkManagerSettings
      (TLSSettingsSimple {
        settingDisableCertificateValidation :: Bool
settingDisableCertificateValidation = Bool
insecure,
        settingDisableSession :: Bool
settingDisableSession = Bool
False,
        settingUseServerName :: Bool
settingUseServerName = Bool
False
      }) Maybe SockSettings
forall a. Maybe a
Nothing
    runResourceT $ do
        response <- C.http request manager
        C.runConduit $ C.responseBody response C..| sinkFile file