content: {- Copyright 2017 NGLess Authors
   - License: MIT
   -}
  module CWL
      ( writeCWL
      ) where
  
  import qualified Data.ByteString as B
  import qualified Data.ByteString.Char8 as B8
  import           Data.Maybe
  import           Control.Monad.Trans.Cont (evalCont, callCC)
  
  import Utils.Utils
  import Language
  
  {- Build a CWL wrapper for the NGLess script
   -
   - Currently, this is very simplistic with little error checking.
   -}
  
  
  build :: FilePath -> [Integer] -> Integer -> String
  build sfname inputs output = concat
      ["cwlVersion: cwl:draft-3\n"
      ,"class: CommandLineTool\n"
      ,"baseCommand: [ngless, ", sfname, "]\n"
      ,"inputs:\n"
      ,buildInputs inputs
      ,builtOutput output
      ]
  
  buildInputs :: [Integer] -> String
  buildInputs = concatMap buildInput
  buildInput :: Integer -> String
  buildInput p = concat
      ["- id: input", show p, "\n"
      ,"  type: Str\n"
      ,"  inputBinding:\n"
      ,"    position: ", show p, "\n"
      ]
  builtOutput p = concat
      ["outputs:\n"
      ,"  -id: nglessout\n"
      ,"  type: File\n"
      ,"  outputBinding:\n"
      ,"    glob: $(inputs.input"++show p++")\n"
      ]
  
  
  extractARGVUsage :: Expression -> Maybe Integer
  extractARGVUsage e = evalCont $ callCC $ \exit -> do
                          recursiveAnalyse (extractARGVUsage' exit) e
                          return Nothing
      where
          extractARGVUsage' exit (IndexExpression (Lookup _ (Variable "ARGV")) (IndexOne (ConstInt ix1))) = exit (Just ix1)
          extractARGVUsage' _ _ = return ()
  
  extractAllARGVUsage :: Script -> [Integer]
  extractAllARGVUsage (Script _ body) = mapMaybe extractARGVUsage (snd <$> body)
  
  extractOutput :: Script -> Integer
  extractOutput (Script _ body) = head $ mapMaybe  extractOutput' (snd <$> body)
      where
          extractOutput' :: Expression -> Maybe Integer
          extractOutput' (FunctionCall (FuncName "write") _ kwargs _) = do
              ofile <- lookup (Variable "ofile") kwargs
              extractARGVUsage ofile
          extractOutput' _ = Nothing
  
  writeCWL :: Script -> FilePath -> FilePath -> IO ()
  writeCWL sc scFname fp =
      withOutputFile fp $ \h ->
          B.hPut h (B8.pack $ buildCWL scFname sc)
  
  buildCWL :: FilePath -> Script -> String
  buildCWL scFname sc = build scFname (extractAllARGVUsage sc) (extractOutput sc)
  