{-# LANGUAGE DeriveGeneric #-}
-- Copyright 2024 United States Government as represented by the Administrator
-- of the National Aeronautics and Space Administration. All Rights Reserved.
--
-- Disclaimers
--
-- Licensed under the Apache License, Version 2.0 (the "License"); you may
-- not use this file except in compliance with the License. You may obtain a
-- copy of the License at
--
--      https://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-- License for the specific language governing permissions and limitations
-- under the License.
--
-- | Ogma projects.
module Data.Project where

-- External imports
import           Control.Exception (IOException, try)
import           Data.Aeson        (FromJSON, ToJSON, eitherDecodeStrict')
import qualified Data.ByteString   as BS
import           GHC.Generics      (Generic)

-- -- Internal imports
import Data.Either.Extra (mapLeft)

data Project = Project
    { Project -> Maybe String
projectName           :: Maybe String
    , Project -> [(String, String, String)]
projectInputFiles     :: [(FilePath, String, String)]
                               -- ^ File, format name, prop name
    , Project -> Maybe String
projectVariableFiles  :: Maybe FilePath
    , Project -> Maybe String
projectVariableDBFile :: Maybe FilePath
    , Project -> Maybe String
projectHandlerFile    :: Maybe FilePath
    , Project -> Maybe String
projectCommandPropVia :: Maybe FilePath
    , Project -> Maybe String
projectTemplateDir    :: Maybe FilePath
    , Project -> Maybe String
projectTargetDir      :: Maybe FilePath
    , Project -> Maybe String
projectExtraJSONFile  :: Maybe FilePath
    }
  deriving ((forall x. Project -> Rep Project x)
-> (forall x. Rep Project x -> Project) -> Generic Project
forall x. Rep Project x -> Project
forall x. Project -> Rep Project x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Project -> Rep Project x
from :: forall x. Project -> Rep Project x
$cto :: forall x. Rep Project x -> Project
to :: forall x. Rep Project x -> Project
Generic, Int -> Project -> ShowS
[Project] -> ShowS
Project -> String
(Int -> Project -> ShowS)
-> (Project -> String) -> ([Project] -> ShowS) -> Show Project
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Project -> ShowS
showsPrec :: Int -> Project -> ShowS
$cshow :: Project -> String
show :: Project -> String
$cshowList :: [Project] -> ShowS
showList :: [Project] -> ShowS
Show)

instance FromJSON Project
instance ToJSON Project

-- | Read a project from a file.
readProject :: FilePath -> IO (Either String Project)
readProject :: String -> IO (Either String Project)
readProject String
path = do
  bytesResult <- IO ByteString -> IO (Either IOException ByteString)
forall e a. Exception e => IO a -> IO (Either e a)
try (String -> IO ByteString
BS.readFile String
path)
  pure $ case bytesResult of
           Left IOException
e      -> String -> Either String Project
forall a b. a -> Either a b
Left (IOException -> String
forall a. Show a => a -> String
show (IOException
e :: IOException))
           Right ByteString
bytes -> ShowS -> Either String Project -> Either String Project
forall a c b. (a -> c) -> Either a b -> Either c b
mapLeft (String
"Failed to read project: " String -> ShowS
forall a. [a] -> [a] -> [a]
++)
                        (Either String Project -> Either String Project)
-> Either String Project -> Either String Project
forall a b. (a -> b) -> a -> b
$ ByteString -> Either String Project
forall a. FromJSON a => ByteString -> Either String a
eitherDecodeStrict' ByteString
bytes