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

import B9.Artifact.Content.Readable
import B9.Artifact.Content.StringTemplate
import B9.QCUtil
import Control.Parallel.Strategies
import Data.Data
import GHC.Generics (Generic)
import System.FilePath ((</>))
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
  = -- | Copy a 'B9.Artifact.Content.StringTemplate.SourceFile'
    -- potentially replacing variable defined in 'Let'-like
    -- parent elements.
    FromFile
      FilePath
      SourceFile
  | -- | Create a file from some 'Content'
    FromContent
      FilePath
      Content
  | -- | Set the unix /file permissions/ to all files generated
    -- by the nested list of 'ArtifactSource's.
    SetPermissions
      Int
      Int
      Int
      [ArtifactSource]
  | -- | Assume a local directory as starting point for all
    -- relative source files in the nested 'ArtifactSource's.
    FromDirectory
      FilePath
      [ArtifactSource]
  | -- | Specify an output directory for all the files
    -- generated by the nested 'ArtifactSource's
    IntoDirectory
      FilePath
      [ArtifactSource]
  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
      ]