module Files where

import Test.HUnit ( assertEqual, Test(..) )

import System.IO ( withFile, IOMode(ReadMode) )

import qualified Data.Text as T
import qualified Data.Text.IO as T

import Data.Text(isInfixOf)

import System.Directory (doesFileExist, doesDirectoryExist, listDirectory)

allTests :: Test
allTests = TestList [
    TestLabel "testFileContains" testFileContains,
    TestLabel "testContainsRecursively" testContainsRecursively
  ]

-------------------------------------------------
-- Aufgabe 1 (a)
-------------------------------------------------
fileContains :: FilePath -> T.Text -> IO Bool
fileContains filePath textToSearch = do
  fileExists <- doesFileExist filePath
  if not fileExists
    then pure False
    else do
      content <- withFile filePath ReadMode (\handle -> T.hGetContents handle) 
      pure (textToSearch `isInfixOf` content)

----------  ---------------------------------------
-- Aufgabe 1 (a) Test
-------------------------------------------------
testFileContains :: Test
testFileContains = TestCase $ do
  containsTest1 <- (fileContains "sample-dir/1.txt" (T.pack "fun to lose"))
  assertEqual "test1" True containsTest1
  containsTest2 <- (fileContains "sample-dir/2.txt" (T.pack "entertain us"))
  assertEqual "test2" True containsTest2
  containsTest3 <- (fileContains "sample-dir/2.txt" (T.pack "entertain yourself"))
  assertEqual "test3" False containsTest3

-------------------------------------------------
-- Aufgabe 1 (b)
-------------------------------------------------
--listDirectory :: FilePath -> IO [FilePath]
containsRecursively :: FilePath -> T.Text -> IO Bool
containsRecursively filePath textToSearchFor = do
  thisIsDirectory <- doesDirectoryExist filePath
  if thisIsDirectory
    then do
      -- Current file path is directory so get all sub directories and files in it.
      subDirectories <- listDirectory filePath
      case subDirectories of
        [] -> pure False
        (first:rest) -> do
          firstIsDirectory <- doesDirectoryExist (filePath ++ "/" ++ first)
          if firstIsDirectory
            -- If first is directory go deeper into left directory tree of first directory.
            -- After that go into right part trees and search their left branches and right
            -- part trees recursively.
            then do
              containsRec <- containsRecursively (filePath ++ "/" ++ first) textToSearchFor
              iterateLi <- iterateList filePath rest textToSearchFor
              if containsRec || iterateLi
                then pure True
                else pure False
            else do
              -- If first is a file, search file for textToSearchFor.
              fileContainsTextInFirst <- fileContains (filePath ++ "/" ++ first) textToSearchFor
              if fileContainsTextInFirst
                then pure True
                -- Iterate through the rest of sub directories.
                else do 
                  iterateList filePath rest textToSearchFor
    -- Current file path is a file so search for textToSearchFor.
    else fileContains filePath textToSearchFor

iterateList :: FilePath -> [FilePath] -> T.Text -> IO Bool
iterateList mainDirectory subDirectories  textToSearchFor =
  case subDirectories of
    [] -> pure False
    (first:rest) -> do
      firstContainsTextRecursively <- containsRecursively (mainDirectory ++ "/" ++ first) textToSearchFor 
      if firstContainsTextRecursively
        then pure True 
        else iterateList mainDirectory rest textToSearchFor

-------------------------------------------------
-- Aufgabe 1 (b) Test
-------------------------------------------------
testContainsRecursively :: Test
testContainsRecursively = TestCase $ do
  containsTest1 <- (containsRecursively "sample-dir" (T.pack "fun to lose"))
  assertEqual "test1" True containsTest1
  containsTest2 <- (containsRecursively "sample-dir" (T.pack "entertain us"))
  assertEqual "test2" True containsTest2
  containsTest3 <- (containsRecursively "sample-dir" (T.pack "hello, hello"))
  assertEqual "test3" True containsTest3
