-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.


{-# LANGUAGE NoRebindableSyntax #-}

-- | Everything needed to run Duckling.

module Duckling.Core
  ( Context(..)
  , Dimension(..)
  , Entity(..)
  , Lang(..)
  , Locale
  , Node(..)
  , Options(..)
  , Range(..)
  , Region(..)
  , ResolvedVal(..)
  , Seal(..)
  , withSeal
  , fromName
  , makeLocale
  , toJText
  , toName

  -- Duckling API
  , parse
  , supportedDimensions
  , allLocales

  -- Reference time builders
  , currentReftime
  , fromZonedTime
  , makeReftime
  ) where

import Data.HashMap.Strict (HashMap)
import Data.Text (Text)
import Data.Time
import Data.Time.LocalTime.TimeZone.Series
import Prelude
import qualified Data.HashMap.Strict as HashMap

import Duckling.Api
import Duckling.Dimensions.Types
import Duckling.Locale
import Duckling.Resolve
import Duckling.Types

-- | Builds a `DucklingTime` for timezone `tz` at `utcTime`.
-- If no `series` found for `tz`, uses UTC.
makeReftime :: HashMap Text TimeZoneSeries -> Text -> UTCTime -> DucklingTime
makeReftime :: HashMap Text TimeZoneSeries -> Text -> UTCTime -> DucklingTime
makeReftime HashMap Text TimeZoneSeries
series Text
tz UTCTime
utcTime = ZoneSeriesTime -> DucklingTime
DucklingTime (ZoneSeriesTime -> DucklingTime) -> ZoneSeriesTime -> DucklingTime
forall a b. (a -> b) -> a -> b
$ UTCTime -> TimeZoneSeries -> ZoneSeriesTime
ZoneSeriesTime UTCTime
ducklingTime TimeZoneSeries
tzs
  where
    tzs :: TimeZoneSeries
tzs = TimeZoneSeries
-> Text -> HashMap Text TimeZoneSeries -> TimeZoneSeries
forall k v. (Eq k, Hashable k) => v -> k -> HashMap k v -> v
HashMap.lookupDefault (TimeZone -> [(UTCTime, TimeZone)] -> TimeZoneSeries
TimeZoneSeries TimeZone
utc []) Text
tz HashMap Text TimeZoneSeries
series
    ducklingTime :: UTCTime
ducklingTime = LocalTime -> UTCTime
toUTC (LocalTime -> UTCTime) -> LocalTime -> UTCTime
forall a b. (a -> b) -> a -> b
$ TimeZoneSeries -> UTCTime -> LocalTime
utcToLocalTime' TimeZoneSeries
tzs UTCTime
utcTime

-- | Builds a `DucklingTime` for timezone `tz` at current time.
-- If no `series` found for `tz`, uses UTC.
currentReftime :: HashMap Text TimeZoneSeries -> Text -> IO DucklingTime
currentReftime :: HashMap Text TimeZoneSeries -> Text -> IO DucklingTime
currentReftime HashMap Text TimeZoneSeries
series Text
tz = do
  UTCTime
utcNow <- IO UTCTime
getCurrentTime
  DucklingTime -> IO DucklingTime
forall (m :: * -> *) a. Monad m => a -> m a
return (DucklingTime -> IO DucklingTime)
-> DucklingTime -> IO DucklingTime
forall a b. (a -> b) -> a -> b
$ HashMap Text TimeZoneSeries -> Text -> UTCTime -> DucklingTime
makeReftime HashMap Text TimeZoneSeries
series Text
tz UTCTime
utcNow

-- | Builds a `DucklingTime` from a `ZonedTime`.
fromZonedTime :: ZonedTime -> DucklingTime
fromZonedTime :: ZonedTime -> DucklingTime
fromZonedTime (ZonedTime LocalTime
localTime TimeZone
timeZone) = ZoneSeriesTime -> DucklingTime
DucklingTime (ZoneSeriesTime -> DucklingTime) -> ZoneSeriesTime -> DucklingTime
forall a b. (a -> b) -> a -> b
$
  UTCTime -> TimeZoneSeries -> ZoneSeriesTime
ZoneSeriesTime (LocalTime -> UTCTime
toUTC LocalTime
localTime) (TimeZone -> [(UTCTime, TimeZone)] -> TimeZoneSeries
TimeZoneSeries TimeZone
timeZone [])