-- | Source files for 'B9.Artifact.Generator's.
--
-- @since 0.5.62
module B9.Artifact.Readable.Source
  ( ArtifactSource(..)
  , getArtifactSourceFiles
  )
where

import           Control.Parallel.Strategies
import           Data.Data
import           GHC.Generics                   ( Generic )
import           System.FilePath                ( (</>) )

import           B9.Artifact.Content.Readable
import           B9.Artifact.Content.StringTemplate
import           B9.QCUtil

import           Test.QuickCheck

-- | Describe how input files for artifacts to build are obtained.  The general
--   structure of each constructor is __FromXXX__ /destination/ /source/
data ArtifactSource
  = FromFile FilePath
             SourceFile
      -- ^ Copy a 'B9.Artifact.Content.StringTemplate.SourceFile'
      -- potentially replacing variable defined in 'Let'-like
      -- parent elements.
  | FromContent FilePath
                Content
      -- ^ Create a file from some 'Content'
  | SetPermissions Int
                   Int
                   Int
                   [ArtifactSource]
      -- ^ Set the unix /file permissions/ to all files generated
      -- by the nested list of 'ArtifactSource's.
  | FromDirectory FilePath
                  [ArtifactSource]
      -- ^ Assume a local directory as starting point for all
      -- relative source files in the nested 'ArtifactSource's.
  | IntoDirectory FilePath
                  [ArtifactSource]
      -- ^ Specify an output directory for all the files
      -- generated by the nested 'ArtifactSource's
  deriving (Read, Show, Eq, Data, Typeable, Generic)

instance NFData ArtifactSource

-- | Return all source files generated by an 'ArtifactSource'.
getArtifactSourceFiles :: ArtifactSource -> [FilePath]
getArtifactSourceFiles (FromContent f _) = [f]
getArtifactSourceFiles (FromFile    f _) = [f]
getArtifactSourceFiles (IntoDirectory pd as) =
  (pd </>) <$> (as >>= getArtifactSourceFiles)
getArtifactSourceFiles (FromDirectory _ as) = as >>= getArtifactSourceFiles
getArtifactSourceFiles (SetPermissions _ _ _ as) =
  as >>= getArtifactSourceFiles

instance Arbitrary ArtifactSource where
  arbitrary = oneof
    [ FromFile <$> smaller arbitraryFilePath <*> smaller arbitrary
    , FromContent <$> smaller arbitraryFilePath <*> smaller arbitrary
    , SetPermissions
    <$> choose (0, 7)
    <*> choose (0, 7)
    <*> choose (0, 7)
    <*> smaller arbitrary
    , FromDirectory <$> smaller arbitraryFilePath <*> smaller arbitrary
    , IntoDirectory <$> smaller arbitraryFilePath <*> smaller arbitrary
    ]