{-# LANGUAGE OverloadedStrings #-}

module Chronos.Date.Text where

import Chronos.Types
import Data.Text (Text)
import Data.Text.Lazy.Builder (Builder)
import Data.Vector (Vector)
import Data.Monoid
import Data.Attoparsec.Text (Parser)
import Control.Monad
import Data.Foldable
import qualified Chronos.Internal.Format as Format
import qualified Chronos.Internal as I
import qualified Data.Text as Text
import qualified Data.Text.Read as Text
import qualified Data.Attoparsec.Text as Atto
import qualified Data.Vector as Vector
import qualified Data.Text.Lazy.Builder as Builder
import qualified Data.Text.Lazy.Builder.Int as Builder

-- | This could be written much more efficiently since we know the
--   exact size the resulting 'Text' will be.
builder_Ymd :: Maybe Char -> Date -> Builder
builder_Ymd msep (Date (Year y) m d) = case msep of
  Nothing ->
       Builder.decimal y
    <> Format.monthToZeroPaddedDigit m
    <> Format.zeroPadDayOfMonth d
  Just sep -> let sepBuilder = Builder.singleton sep in
       Builder.decimal y
    <> sepBuilder
    <> Format.monthToZeroPaddedDigit m
    <> sepBuilder
    <> Format.zeroPadDayOfMonth d

parser_Ymd :: Maybe Char -> Parser Date
parser_Ymd msep = do
  y <- I.parseFixedDigits 4
  traverse_ Atto.char msep
  m <- I.parseFixedDigits 2
  when (m < 1 || m > 12) (fail "month must be between 1 and 12")
  traverse_ Atto.char msep
  d <- I.parseFixedDigits 2
  when (d < 1 || d > 31) (fail "day must be between 1 and 31")
  return (Date (Year y) (Month $ m - 1) (DayOfMonth d))