{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}

module Data.Taskell.Date.RelativeParser
    ( parseRelative
    ) where

import ClassyPrelude

import Data.Attoparsec.Text

import Data.Time.Clock (addUTCTime)

import Utility.Parser (lexeme)

-- relative date parsing
minute :: Int
minute = 60

hour :: Int
hour = minute * 60

day :: Int
day = hour * 24

week :: Int
week = day * 7

periodP :: Char -> Parser Int
periodP c = lexeme decimal <* char c

wP :: Parser Int
wP = (* week) <$> periodP 'w'

dP :: Parser Int
dP = (* day) <$> periodP 'd'

hP :: Parser Int
hP = (* hour) <$> periodP 'h'

mP :: Parser Int
mP = (* minute) <$> periodP 'm'

sP :: Parser Int
sP = periodP 's'

relativeP :: UTCTime -> Parser (Maybe UTCTime)
relativeP now =
    lexeme $ do
        period <- fromIntegral . sum <$> many1 (sP <|> mP <|> hP <|> dP <|> wP)
        pure $ Just (addUTCTime period now)

parseRelative :: UTCTime -> Text -> Either Text UTCTime
parseRelative now text =
    case parseOnly (relativeP now) text of
        Right (Just time) -> Right time
        _                 -> Left "Could not parse date."