{-
-- EPITECH PROJECT, 2026
-- Glados
-- File description:
-- Header
-}

module Common.Utils.Bytecode.Header
    ( extractContentIfValidHeader
    , evaluateHeader
    , hasValidSize
    , hasValidMagic
    , hasValidVersion
    ) where

import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as C8
import System.Exit (exitWith, ExitCode(..))

-- | Checks if the file is large enough to contain a header (10 bytes).
--
hasValidSize :: BS.ByteString -> Bool
hasValidSize :: ByteString -> Bool
hasValidSize ByteString
bs = ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
10

-- | Checks if the Magic Number is "GLAD" (0x47 0x4C 0x41 0x44).
--
hasValidMagic :: BS.ByteString -> Bool
hasValidMagic :: ByteString -> Bool
hasValidMagic ByteString
bs = Int -> ByteString -> ByteString
BS.take Int
4 ByteString
bs ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== String -> ByteString
C8.pack String
"GLAD"

-- | Checks if the Version is supported (0x02).
--
hasValidVersion :: BS.ByteString -> Bool
hasValidVersion :: ByteString -> Bool
hasValidVersion ByteString
bs = HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bs Int
4 Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x02

-- | Evaluates the header validity by combining all predicates.
--
-- @details
--   Uses short-circuit boolean logic (&&).
--   Order matters: 'hasValidSize' must be checked first to prevent
--   segmentation faults in 'hasValidVersion'.
--
evaluateHeader :: BS.ByteString -> Bool
evaluateHeader :: ByteString -> Bool
evaluateHeader ByteString
bs = ByteString -> Bool
hasValidSize ByteString
bs Bool -> Bool -> Bool
&& ByteString -> Bool
hasValidMagic ByteString
bs Bool -> Bool -> Bool
&& ByteString -> Bool
hasValidVersion ByteString
bs

-- | Validates the .gla file header and returns the raw bytecode.
--
-- @details
--   If the header is valid, drops the 10-byte header and returns the code.
--   If invalid, prints a generic error and exits.
--
extractContentIfValidHeader :: BS.ByteString -> IO BS.ByteString
extractContentIfValidHeader :: ByteString -> IO ByteString
extractContentIfValidHeader ByteString
content =
    case ByteString -> Bool
evaluateHeader ByteString
content of
        Bool
True  -> ByteString -> IO ByteString
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> ByteString -> ByteString
BS.drop Int
10 ByteString
content)
        Bool
False -> String -> IO ()
putStrLn String
"\ESC[31mInvalid File: Bad Header.\ESC[0m" IO () -> IO ByteString -> IO ByteString
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>
            ExitCode -> IO ByteString
forall a. ExitCode -> IO a
exitWith (Int -> ExitCode
ExitFailure Int
84)