content: {-# OPTIONS_GHC -Wno-type-defaults #-}
  
  -- | Extract sounded parts, and combine again
  module Cut.CutVideo
    ( extract
    , Interval(..)
    , Silent
    , Sound
    , combine
    , combineOutput
    , combineDir
    )
  where
  
  import           Control.Lens
  import           Control.Monad
  import           Control.Monad.Catch
  import           Cut.Analyze
  import           Cut.Shell
  import           Cut.Options
  import           Data.Foldable
  import           Data.Text           (Text)
  import qualified Data.Text           as Text
  import           Data.Text.Lens
  import           Shelly              hiding (FilePath, shelly)
  import           Text.Printf         (printf)
  
  -- | convert a sounded interval into a filename where we write the temporary extracted file in
  toFileName :: ListenCutOptions -> FilePath -> Interval Sound -> FilePath
  toFileName options tmp inter = tmp
           </> getOutFileName options
           <> "-"
           <> fname
           <> ".mkv"
    where
        fname    = printf "%010d" (truncate $ interval_start inter * 100 :: Integer)
  
  toArgs :: ListenCutOptions -> FilePath -> Interval Sound -> (Interval Sound, [Text])
  toArgs options tmp inter =
    ( inter
    , -- keep ter interval for debugging
      ["-y", "-ss", start, "-t", duration, "-i", options ^. lc_fileio . in_file . packed]
      <> specifyTracks options
      <> [ Text.pack $ toFileName options tmp inter
         ]
    )
   where
    start    = floatToText $ interval_start inter
    duration = floatToText $ interval_duration inter
  
  extractDir :: FilePath
  extractDir = "extract"
  
  extract :: ListenCutOptions -> FilePath -> [Interval Sound] -> IO ()
  extract options tempDir intervals = do
    shelly $ mkdir_p exdir
    traverse_
        (\(inter, args) -> void $ catch (shelly $ ffmpeg' args) $ \exec -> do
          liftIO
            (print ("expection during edit: ", exec :: SomeException, args, inter)
            )
          pure ["expection"]
        )
      $   toArgs options exdir <$> intervals
    liftIO $ putStrLn "finished extracting"
  
    where
      exdir = tempDir </> extractDir
  
  combineOutput :: FilePath
  combineOutput = "combined-output.mkv"
  
  combine :: FilePath -> Sh ()
  combine tempDir = do
    output' <- ffmpeg' args
    liftIO $ print ("output", output')
   where -- https://stackoverflow.com/questions/7333232/how-to-concatenate-two-mp4-files-using-ffmpeg
    args =
      [ "-y"
      , "-f"
      , "concat"
      , "-safe"
      , "0"
      , "-i"
      , Text.pack (tempDir <> "/input.txt")
      , "-c"
      , "copy"
      , Text.pack $ tempDir </> combineOutput
      ]
  
  combineDir :: ListenCutOptions -> FilePath -> [Interval Sound] -> Sh ()
  combineDir options tempDir intervals = do
    liftIO $ putStrLn "start combining the dir"
    let paths = Text.unlines $ flip (<>) "'" . ("file '" <>) <$> res
    writefile (fromText $ Text.pack $ tempDir <> "/input.txt") paths
    combine tempDir
    where
      res = Text.pack . toFileName options exdir <$> intervals
      -- for relative dirs ffmpeg doesn't accept prepending of tempdir
      exdir = if hasWorkDir then extractDir else tempDir </> extractDir
      hasWorkDir :: Bool
      hasWorkDir = has (lc_fileio . work_dir . _Just) options
  