{-# LANGUAGE ViewPatterns #-}

module Data.Thyme.Format.Internal where

import Prelude
import Control.Applicative
import Data.Attoparsec.ByteString.Char8 (Parser)
import qualified Data.Attoparsec.ByteString.Char8 as P
import qualified Data.ByteString.Char8 as S
import Data.Char
import Data.Int
import Data.Micro

{-# INLINE shows02 #-}
shows02 :: Int -> String -> String
shows02 n = if n < 10 then (:) '0' . shows n else shows n

{-# INLINE shows_2 #-}
shows_2 :: Int -> String -> String
shows_2 n = if n < 10 then (:) ' ' . shows n else shows n

{-# INLINE shows03 #-}
shows03 :: Int -> ShowS
shows03 n
    | n < 10 = (++) "00" . shows n
    | n < 100 = (++) "0" . shows n
    | otherwise = shows n

{-# INLINE shows04 #-}
shows04 :: Int -> String -> String
shows04 n
    | n < 10 = (++) "000" . shows n
    | n < 100 = (++) "00" . shows n
    | n < 1000 = (++) "0" . shows n
    | otherwise = shows n

------------------------------------------------------------------------

{-
{-# INLINEABLE indexOfCI #-}
indexOfCI :: (Alternative m, Monad m) =>
    [String] -> (Int -> String -> m k) -> (String -> m k)
indexOfCI l k input = uncurry k =<< foldr (<|>) no (zipWith match l [0..]) where
    match s i = stringCI s (return . (,) i) input
    no = fail $ "Expected month at " ++ show input
-}

-- | Number may be prefixed with '-'
{-# INLINE negative #-}
negative :: Parser Int64 -> Parser Int64
negative p = ($) <$> (negate <$ P.char '-' <|> pure id) <*> p

-- | Fixed-length 0-padded decimal
{-# INLINEABLE dec0 #-}
dec0 :: Int -> Parser Int
dec0 n = either fail return . P.parseOnly P.decimal =<< P.take n

-- | Fixed-length space-padded decimal
{-# INLINEABLE dec_ #-}
dec_ :: Int -> Parser Int
dec_ n = either fail return . P.parseOnly P.decimal
    =<< S.dropWhile isSpace <$> P.take n

{-# INLINEABLE micro #-}
micro :: Parser Micro
micro = do
    us10 <- either fail return . P.parseOnly P.decimal . S.take 7
        . (`S.append` S.pack "000000") =<< P.takeWhile1 isDigit
    return $ Micro (div (us10 + 5) 10)