module Data.Aviation.Aip.RunAipRecords( run ) where import Control.Applicative(pure, (<**>)) import Control.Category((.)) import Control.Exception(IOException) import Control.Lens import Control.Monad(when, unless) import Control.Monad.Catch(MonadCatch(catch)) import Control.Monad.IO.Class(liftIO) import Control.Monad.Trans.Except(runExceptT) import Data.Aviation.Aip.AipCon(AipCon) import Data.Aviation.Aip.AipOptions(parserAipOptions, aipOptionLog, aipOptionCache, aipOptionOutputDirectory) import Data.Aviation.Aip.AipRecords(AipRecords, getAipRecords) import Data.Aviation.Aip.Cache(Cache) import Data.Aviation.Aip.Href(ManyHref(_ManyHref), aipPrefix) import Data.Aviation.Aip.Log(aiplog, aiplog') import Data.Aviation.Aip.OnAipRecords(OnAipRecords(OnAipRecords), OnAipRecordsIO) import Data.Aviation.Aip.PerHref(PerHref(PerHref), PerHrefAipCon) import Data.Aviation.Aip.SHA1(_GetSHA1, strHash) import Data.Either(Either(Left, Right)) import Data.Function(($)) import Data.Semigroup(Semigroup((<>))) import Options.Applicative(execParser, info, helper, fullDesc, header) import Prelude(show) import System.Directory(doesDirectoryExist, removeDirectoryRecursive) import System.Exit(exitWith, ExitCode(ExitFailure)) import System.FilePath(FilePath, (</>)) import System.IO(IO) run :: PerHrefAipCon () -> OnAipRecordsIO () -> IO () run k (OnAipRecords l) = let writeAip :: PerHrefAipCon () -> Cache -> FilePath -> AipCon (Either IOException (FilePath, AipRecords)) writeAip (PerHref w) cch dir = let catchIOException :: MonadCatch m => m a -> (IOException -> m a) -> m a catchIOException = catch in do let dir' = dir </> "sha1" x <- getAipRecords cch dir' let h = dir' </> view (_GetSHA1 . re strHash) x de <- liftIO $ doesDirectoryExist h let dl = mapMOf_ _ManyHref (\c -> w c dir h aiplog) (aipPrefix x) catchIOException (do de `unless` dl pure (Right (h, x))) (\e -> do aiplog ("IO Exception: " <> show e) liftIO $ removeDirectoryRecursive h pure (Left e)) p = execParser (info (parserAipOptions <**> helper) ( fullDesc <> header "aip 0.1.1 <http://www.airservicesaustralia.com/aip/aip.asp>" ) ) in do opts <- p let lg = (opts ^. aipOptionLog) let dir = opts ^. aipOptionOutputDirectory e <- runExceptT ((writeAip k (opts ^. aipOptionCache) dir ^. _Wrapped) lg) case e of Left e' -> do when lg (aiplog' ("network or HTTP error " <> show e')) exitWith (ExitFailure 1) Right r -> l r aiplog' dir