{- SPDX-FileCopyrightText: 2020 Serokell <https://serokell.io/>
 -
 - SPDX-License-Identifier: MPL-2.0
 -}

module Test.Utf8.Choice where

import GHC.IO.Encoding (char8, latin1, textEncodingName, utf8)
import System.IO.Temp (withSystemTempFile)

import qualified System.IO as IO

import Test.HUnit (Assertion, assertFailure)
import Test.Tasty.HUnit ((@=?))

import System.IO (hIsTerminalDevice)
import System.IO.Utf8.Internal (EncodingAction (..), chooseBestEnc, chooseBestEncPure)

import qualified System.IO.Utf8 as Utf8

import Test.Util (withTerminalIn, withTmpFileIn)


-- | Compare @chooseBestEnc@ with @chooseBestEncPure@ on the handle.
verifyOn :: IO.Handle -> Assertion
verifyOn h = do
  isTerm <- IO.hIsTerminalDevice h
  enc <- IO.hGetEncoding h

  let pureResult = chooseBestEncPure isTerm (textEncodingName <$> enc)
  realResult <- chooseBestEnc h hIsTerminalDevice enc

  case (pureResult, realResult) of
    (Nothing, Keep) -> pure ()
    (Just pureName, ChangeFromTo _ realName) -> do
      pureName @=? realName
    (_, _) -> assertFailure "Action mismatch"


unit_pure_binary_file :: Assertion
unit_pure_binary_file =
  Nothing @=? chooseBestEncPure False Nothing

unit_pure_binary_term :: Assertion
unit_pure_binary_term =
  Nothing @=? chooseBestEncPure True Nothing

unit_pure_term_ascii :: Assertion
unit_pure_term_ascii =
  Just "ASCII//TRANSLIT" @=? chooseBestEncPure True (Just "ASCII")

unit_pure_term_utf8 :: Assertion
unit_pure_term_utf8 =
  Nothing @=? chooseBestEncPure True (Just "UTF-8")

unit_pure_file_ascii :: Assertion
unit_pure_file_ascii =
  Just "UTF-8" @=? chooseBestEncPure False (Just "ASCII")

unit_pure_file_utf8 :: Assertion
unit_pure_file_utf8 =
  Nothing @=? chooseBestEncPure False (Just "UTF-8")

unit_pure_idempotent :: Assertion
unit_pure_idempotent =
  Nothing @=? chooseBestEncPure True (Just "ASCII//TRANSLIT")


unit_term_binary :: Assertion
unit_term_binary = withTerminalIn utf8 $ \h -> do
  IO.hSetBinaryMode h True
  verifyOn h

unit_term_utf8 :: Assertion
unit_term_utf8 = withTerminalIn utf8 verifyOn

unit_term_char8 :: Assertion
unit_term_char8 = withTerminalIn char8 verifyOn

unit_term_latin1 :: Assertion
unit_term_latin1 = withTerminalIn latin1 verifyOn


unit_file_binary :: Assertion
unit_file_binary = withSystemTempFile "utf8.bin" $ \_ h -> do
  IO.hSetBinaryMode h True
  verifyOn h

unit_file_utf8 :: Assertion
unit_file_utf8 = withTmpFileIn utf8 verifyOn

unit_file_char8 :: Assertion
unit_file_char8 = withTmpFileIn char8 verifyOn

unit_file_latin1 :: Assertion
unit_file_latin1 = withTmpFileIn latin1 verifyOn

unit_term_idempotent :: Assertion
unit_term_idempotent = withTerminalIn char8 $ \h -> do
  Just enc <- IO.hGetEncoding h
  "ISO-8859-1" @=? textEncodingName enc  -- sanity check
  Utf8.withHandle h $ do
    -- XXX: Actually not true, there is no suffix in the name
    -- Just enc' <- IO.hGetEncoding h
    -- "ISO-8859-1//TRANSLIT" @=? textEncodingName enc'  -- sanity check
    verifyOn h