{-# LANGUAGE
    QuasiQuotes
  , RecordWildCards
  , UnicodeSyntax
  #-}
-- |An internal module for generating Haskell modules eith an
-- arbitrary file implanted.
module Network.HTTP.Lucu.Implant
    ( Input(..)

    , originalLen
    , gzippedLen
    , useGZip

    , openInput
    )
    where
import Codec.Compression.GZip
import Control.Applicative
import qualified Data.ByteString.Lazy as L
import Data.Convertible.Base
import Data.Convertible.Instances.Ascii ()
import Data.Digest.Pure.SHA
import Data.Maybe
import Data.Time
import Network.HTTP.Lucu.ETag
import Network.HTTP.Lucu.MIMEType
import Network.HTTP.Lucu.MIMEType.DefaultExtensionMap
import Network.HTTP.Lucu.MIMEType.Guess
import Network.HTTP.Lucu.Utils
import Prelude.Unicode

data Input
    = Input {
        iPath     !FilePath
      , iLastMod  !UTCTime
      , iType     !MIMEType
      , iETag     !ETag
      , iRawData  !L.ByteString
      , iGZipped  !L.ByteString
      }

originalLen  Input  Integer
originalLen (Input {..})
    = fromIntegral $ L.length iRawData

gzippedLen  Input  Integer
gzippedLen (Input {..})
    = fromIntegral $ L.length iGZipped

useGZip  Input  Bool
useGZip i
    = originalLen i  gzippedLen i

openInput  FilePath  Maybe MIMEType  Maybe ETag  IO Input
openInput fpath ctype etag
    = do lastMod  lastModified fpath
         input    openInputFile fpath
         return Input {
                  iPath    = fpath
                , iLastMod = lastMod
                , iType    = fromMaybe octetStream
                             $ ctype <|> guessType fpath
                , iETag    = fromMaybe (mkETagFromInput input) etag
                , iRawData = input
                , iGZipped = compressWith compParams input
                }
    where
      octetStream  MIMEType
      octetStream = [mimeType| application/octet-stream |]

      compParams  CompressParams
      compParams = defaultCompressParams {
                     compressLevel = bestCompression
                   }

lastModified  FilePath  IO UTCTime
lastModified "-"   = getCurrentTime
lastModified fpath = getLastModified fpath

openInputFile  FilePath  IO L.ByteString
openInputFile "-"   = L.getContents
openInputFile fpath = L.readFile fpath

guessType  FilePath  Maybe MIMEType
guessType = guessTypeByFileName defaultExtensionMap

mkETagFromInput  L.ByteString  ETag
mkETagFromInput input
    = strongETag $ convertUnsafe
                 $ "SHA-1:"  showDigest (sha1 input)