{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances #-}
module Data.HodaTime.Pattern.ApplyParse
(
   DefaultForParse(..)
  ,ApplyParse(..)
  ,ZonedDateTimeInfo(..)
  ,DateTimeInfo(..)
  ,TimeInfo(..)
  ,DateInfo(..)
)
where

import Data.HodaTime.LocalTime.Internal (LocalTime(..), localTime)
import Data.HodaTime.CalendarDateTime.Internal (IsCalendar(..), Date, CalendarDateTime(..), at)
import Data.HodaTime.Pattern.ParseTypes
import Control.Monad.Catch (MonadThrow)

defaultTime :: TimeInfo
defaultTime :: TimeInfo
defaultTime = Int -> Int -> Int -> Int -> TimeInfo
TimeInfo Int
0 Int
0 Int
0 Int
0

-- Class

class DefaultForParse d where
  getDefault :: d

instance DefaultForParse LocalTime where
  getDefault :: LocalTime
getDefault = Word32 -> Word32 -> LocalTime
LocalTime Word32
0 Word32
0

instance IsCalendar cal => DefaultForParse (Date cal) where
  getDefault :: Date cal
getDefault = Int32 -> Date cal
forall cal. IsCalendar cal => Int32 -> Date cal
fromDays Int32
0   -- the calendar's epoch; parsing overwrites the fields, so any valid date works

instance IsCalendar cal => DefaultForParse (CalendarDateTime cal) where
  getDefault :: CalendarDateTime cal
getDefault = Date cal
forall d. DefaultForParse d => d
getDefault Date cal -> LocalTime -> CalendarDateTime cal
forall cal. Date cal -> LocalTime -> CalendarDateTime cal
`at` LocalTime
forall d. DefaultForParse d => d
getDefault


class ApplyParse a b | b -> a where
  applyParse :: MonadThrow m => (a -> a) -> m b

instance ApplyParse TimeInfo LocalTime where
  applyParse :: forall (m :: * -> *).
MonadThrow m =>
(TimeInfo -> TimeInfo) -> m LocalTime
applyParse TimeInfo -> TimeInfo
f = Int -> Int -> Int -> Int -> m LocalTime
forall (m :: * -> *).
MonadThrow m =>
Int -> Int -> Int -> Int -> m LocalTime
localTime (TimeInfo -> Int
_hour TimeInfo
ti) (TimeInfo -> Int
_minute TimeInfo
ti) (TimeInfo -> Int
_second TimeInfo
ti) (TimeInfo -> Int
_nanoSecond TimeInfo
ti)
    where
      ti :: TimeInfo
ti = TimeInfo -> TimeInfo
f TimeInfo
defaultTime

instance IsCalendar cal => ApplyParse (DateInfo cal) (Date cal) where
  applyParse :: forall (m :: * -> *).
MonadThrow m =>
(DateInfo cal -> DateInfo cal) -> m (Date cal)
applyParse DateInfo cal -> DateInfo cal
_ = m (Date cal)
forall a. HasCallStack => a
undefined

{- class ApplyParse r where
  type StartData r
  getStartData :: StartData r
  applyParse :: StartData r -> r

instance ApplyParse LocalTime where
  type StartData LocalTime = TimeInfo
  getStartData = defaultTime

instance IsCalendar cal => ApplyParse (CalendarDate cal) where
  type StartData LocalTime = DateInfo cal
  getStartData = defaultDate

instance IsCalendar cal => ApplyParse (CalendarDateTime cal) where
  type StartData r = DateTimeInfo
  getStartData = defaultDateTime

instance IsCalendar cal => ApplyParse (ZonedDateTimeInfo cal) where
  type StartData r = ZonedDateTimeInfo
  getStartData = defaultDateTime "UTC" -}