{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE RecordWildCards #-}

module Cursor.FuzzyLocalTime
  ( FuzzyLocalTimeCursor (..),
    emptyFuzzyLocalTimeCursor,
    makeFuzzyLocalTimeCursor,
    rebuildFuzzyLocalTimeCursorForwards,
    rebuildFuzzyLocalTimeCursorBackwards,
    fuzzyLocalTimeCursorTextCursorL,
    fuzzyLocalTimeCursorGuessForwards,
    fuzzyLocalTimeCursorGuessBackwards,
  )
where

import Control.DeepSeq
import Cursor.Text
import Data.FuzzyTime
import Data.Maybe
import qualified Data.Text as T
import Data.Time
import Data.Validity
import GHC.Generics (Generic)
import Lens.Micro
import Text.Megaparsec

data FuzzyLocalTimeCursor = FuzzyLocalTimeCursor
  { FuzzyLocalTimeCursor -> TextCursor
fuzzyLocalTimeCursorTextCursor :: TextCursor,
    FuzzyLocalTimeCursor -> LocalTime
fuzzyLocalTimeCursorBaseLocalTime :: LocalTime
  }
  deriving (Int -> FuzzyLocalTimeCursor -> ShowS
[FuzzyLocalTimeCursor] -> ShowS
FuzzyLocalTimeCursor -> String
(Int -> FuzzyLocalTimeCursor -> ShowS)
-> (FuzzyLocalTimeCursor -> String)
-> ([FuzzyLocalTimeCursor] -> ShowS)
-> Show FuzzyLocalTimeCursor
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FuzzyLocalTimeCursor -> ShowS
showsPrec :: Int -> FuzzyLocalTimeCursor -> ShowS
$cshow :: FuzzyLocalTimeCursor -> String
show :: FuzzyLocalTimeCursor -> String
$cshowList :: [FuzzyLocalTimeCursor] -> ShowS
showList :: [FuzzyLocalTimeCursor] -> ShowS
Show, FuzzyLocalTimeCursor -> FuzzyLocalTimeCursor -> Bool
(FuzzyLocalTimeCursor -> FuzzyLocalTimeCursor -> Bool)
-> (FuzzyLocalTimeCursor -> FuzzyLocalTimeCursor -> Bool)
-> Eq FuzzyLocalTimeCursor
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FuzzyLocalTimeCursor -> FuzzyLocalTimeCursor -> Bool
== :: FuzzyLocalTimeCursor -> FuzzyLocalTimeCursor -> Bool
$c/= :: FuzzyLocalTimeCursor -> FuzzyLocalTimeCursor -> Bool
/= :: FuzzyLocalTimeCursor -> FuzzyLocalTimeCursor -> Bool
Eq, (forall x. FuzzyLocalTimeCursor -> Rep FuzzyLocalTimeCursor x)
-> (forall x. Rep FuzzyLocalTimeCursor x -> FuzzyLocalTimeCursor)
-> Generic FuzzyLocalTimeCursor
forall x. Rep FuzzyLocalTimeCursor x -> FuzzyLocalTimeCursor
forall x. FuzzyLocalTimeCursor -> Rep FuzzyLocalTimeCursor x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. FuzzyLocalTimeCursor -> Rep FuzzyLocalTimeCursor x
from :: forall x. FuzzyLocalTimeCursor -> Rep FuzzyLocalTimeCursor x
$cto :: forall x. Rep FuzzyLocalTimeCursor x -> FuzzyLocalTimeCursor
to :: forall x. Rep FuzzyLocalTimeCursor x -> FuzzyLocalTimeCursor
Generic)

instance Validity FuzzyLocalTimeCursor

instance NFData FuzzyLocalTimeCursor

emptyFuzzyLocalTimeCursor :: LocalTime -> FuzzyLocalTimeCursor
emptyFuzzyLocalTimeCursor :: LocalTime -> FuzzyLocalTimeCursor
emptyFuzzyLocalTimeCursor LocalTime
d =
  FuzzyLocalTimeCursor
    { fuzzyLocalTimeCursorTextCursor :: TextCursor
fuzzyLocalTimeCursorTextCursor = TextCursor
emptyTextCursor,
      fuzzyLocalTimeCursorBaseLocalTime :: LocalTime
fuzzyLocalTimeCursorBaseLocalTime = LocalTime
d
    }

makeFuzzyLocalTimeCursor :: AmbiguousLocalTime -> FuzzyLocalTimeCursor
makeFuzzyLocalTimeCursor :: AmbiguousLocalTime -> FuzzyLocalTimeCursor
makeFuzzyLocalTimeCursor AmbiguousLocalTime
alt =
  FuzzyLocalTimeCursor
    { fuzzyLocalTimeCursorTextCursor :: TextCursor
fuzzyLocalTimeCursorTextCursor =
        Maybe TextCursor -> TextCursor
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe TextCursor -> TextCursor) -> Maybe TextCursor -> TextCursor
forall a b. (a -> b) -> a -> b
$
          Text -> Maybe TextCursor
makeTextCursor (Text -> Maybe TextCursor) -> Text -> Maybe TextCursor
forall a b. (a -> b) -> a -> b
$
            String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$
              case AmbiguousLocalTime
alt of
                OnlyDaySpecified Day
d -> TimeLocale -> String -> Day -> String
forall t. FormatTime t => TimeLocale -> String -> t -> String
formatTime TimeLocale
defaultTimeLocale String
"%F" Day
d
                BothTimeAndDay LocalTime
lt -> TimeLocale -> String -> LocalTime -> String
forall t. FormatTime t => TimeLocale -> String -> t -> String
formatTime TimeLocale
defaultTimeLocale String
"%F %T%Q" LocalTime
lt,
      fuzzyLocalTimeCursorBaseLocalTime :: LocalTime
fuzzyLocalTimeCursorBaseLocalTime =
        case AmbiguousLocalTime
alt of
          OnlyDaySpecified Day
d -> Day -> TimeOfDay -> LocalTime
LocalTime Day
d TimeOfDay
midnight
          BothTimeAndDay LocalTime
lt -> LocalTime
lt
    }

rebuildFuzzyLocalTimeCursorForwards :: FuzzyLocalTimeCursor -> AmbiguousLocalTime
rebuildFuzzyLocalTimeCursorForwards :: FuzzyLocalTimeCursor -> AmbiguousLocalTime
rebuildFuzzyLocalTimeCursorForwards fdc :: FuzzyLocalTimeCursor
fdc@FuzzyLocalTimeCursor {TextCursor
LocalTime
fuzzyLocalTimeCursorTextCursor :: FuzzyLocalTimeCursor -> TextCursor
fuzzyLocalTimeCursorBaseLocalTime :: FuzzyLocalTimeCursor -> LocalTime
fuzzyLocalTimeCursorTextCursor :: TextCursor
fuzzyLocalTimeCursorBaseLocalTime :: LocalTime
..} =
  AmbiguousLocalTime
-> Maybe AmbiguousLocalTime -> AmbiguousLocalTime
forall a. a -> Maybe a -> a
fromMaybe (LocalTime -> AmbiguousLocalTime
BothTimeAndDay LocalTime
fuzzyLocalTimeCursorBaseLocalTime) (Maybe AmbiguousLocalTime -> AmbiguousLocalTime)
-> Maybe AmbiguousLocalTime -> AmbiguousLocalTime
forall a b. (a -> b) -> a -> b
$ FuzzyLocalTimeCursor -> Maybe AmbiguousLocalTime
fuzzyLocalTimeCursorGuessForwards FuzzyLocalTimeCursor
fdc

rebuildFuzzyLocalTimeCursorBackwards :: FuzzyLocalTimeCursor -> AmbiguousLocalTime
rebuildFuzzyLocalTimeCursorBackwards :: FuzzyLocalTimeCursor -> AmbiguousLocalTime
rebuildFuzzyLocalTimeCursorBackwards fdc :: FuzzyLocalTimeCursor
fdc@FuzzyLocalTimeCursor {TextCursor
LocalTime
fuzzyLocalTimeCursorTextCursor :: FuzzyLocalTimeCursor -> TextCursor
fuzzyLocalTimeCursorBaseLocalTime :: FuzzyLocalTimeCursor -> LocalTime
fuzzyLocalTimeCursorTextCursor :: TextCursor
fuzzyLocalTimeCursorBaseLocalTime :: LocalTime
..} =
  AmbiguousLocalTime
-> Maybe AmbiguousLocalTime -> AmbiguousLocalTime
forall a. a -> Maybe a -> a
fromMaybe (LocalTime -> AmbiguousLocalTime
BothTimeAndDay LocalTime
fuzzyLocalTimeCursorBaseLocalTime) (Maybe AmbiguousLocalTime -> AmbiguousLocalTime)
-> Maybe AmbiguousLocalTime -> AmbiguousLocalTime
forall a b. (a -> b) -> a -> b
$ FuzzyLocalTimeCursor -> Maybe AmbiguousLocalTime
fuzzyLocalTimeCursorGuessBackwards FuzzyLocalTimeCursor
fdc

fuzzyLocalTimeCursorTextCursorL :: Lens' FuzzyLocalTimeCursor TextCursor
fuzzyLocalTimeCursorTextCursorL :: Lens' FuzzyLocalTimeCursor TextCursor
fuzzyLocalTimeCursorTextCursorL =
  (FuzzyLocalTimeCursor -> TextCursor)
-> (FuzzyLocalTimeCursor -> TextCursor -> FuzzyLocalTimeCursor)
-> Lens' FuzzyLocalTimeCursor TextCursor
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens FuzzyLocalTimeCursor -> TextCursor
fuzzyLocalTimeCursorTextCursor ((FuzzyLocalTimeCursor -> TextCursor -> FuzzyLocalTimeCursor)
 -> Lens' FuzzyLocalTimeCursor TextCursor)
-> (FuzzyLocalTimeCursor -> TextCursor -> FuzzyLocalTimeCursor)
-> Lens' FuzzyLocalTimeCursor TextCursor
forall a b. (a -> b) -> a -> b
$ \FuzzyLocalTimeCursor
fdc TextCursor
tc -> FuzzyLocalTimeCursor
fdc {fuzzyLocalTimeCursorTextCursor = tc}

fuzzyLocalTimeCursorGuessForwards :: FuzzyLocalTimeCursor -> Maybe AmbiguousLocalTime
fuzzyLocalTimeCursorGuessForwards :: FuzzyLocalTimeCursor -> Maybe AmbiguousLocalTime
fuzzyLocalTimeCursorGuessForwards FuzzyLocalTimeCursor {TextCursor
LocalTime
fuzzyLocalTimeCursorTextCursor :: FuzzyLocalTimeCursor -> TextCursor
fuzzyLocalTimeCursorBaseLocalTime :: FuzzyLocalTimeCursor -> LocalTime
fuzzyLocalTimeCursorTextCursor :: TextCursor
fuzzyLocalTimeCursorBaseLocalTime :: LocalTime
..} = do
  FuzzyLocalTime
ftod <- Parsec Void Text FuzzyLocalTime -> Text -> Maybe FuzzyLocalTime
forall e s a. (Ord e, Stream s) => Parsec e s a -> s -> Maybe a
parseMaybe Parsec Void Text FuzzyLocalTime
fuzzyLocalTimeP (Text -> Maybe FuzzyLocalTime) -> Text -> Maybe FuzzyLocalTime
forall a b. (a -> b) -> a -> b
$ TextCursor -> Text
rebuildTextCursor TextCursor
fuzzyLocalTimeCursorTextCursor
  LocalTime -> FuzzyLocalTime -> Maybe AmbiguousLocalTime
resolveLocalTimeForwards LocalTime
fuzzyLocalTimeCursorBaseLocalTime FuzzyLocalTime
ftod

fuzzyLocalTimeCursorGuessBackwards :: FuzzyLocalTimeCursor -> Maybe AmbiguousLocalTime
fuzzyLocalTimeCursorGuessBackwards :: FuzzyLocalTimeCursor -> Maybe AmbiguousLocalTime
fuzzyLocalTimeCursorGuessBackwards FuzzyLocalTimeCursor {TextCursor
LocalTime
fuzzyLocalTimeCursorTextCursor :: FuzzyLocalTimeCursor -> TextCursor
fuzzyLocalTimeCursorBaseLocalTime :: FuzzyLocalTimeCursor -> LocalTime
fuzzyLocalTimeCursorTextCursor :: TextCursor
fuzzyLocalTimeCursorBaseLocalTime :: LocalTime
..} = do
  FuzzyLocalTime
ftod <- Parsec Void Text FuzzyLocalTime -> Text -> Maybe FuzzyLocalTime
forall e s a. (Ord e, Stream s) => Parsec e s a -> s -> Maybe a
parseMaybe Parsec Void Text FuzzyLocalTime
fuzzyLocalTimeP (Text -> Maybe FuzzyLocalTime) -> Text -> Maybe FuzzyLocalTime
forall a b. (a -> b) -> a -> b
$ TextCursor -> Text
rebuildTextCursor TextCursor
fuzzyLocalTimeCursorTextCursor
  LocalTime -> FuzzyLocalTime -> Maybe AmbiguousLocalTime
resolveLocalTimeBackwards LocalTime
fuzzyLocalTimeCursorBaseLocalTime FuzzyLocalTime
ftod