-- 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 GADTs #-}

module Duckling.Duration.Helpers
  ( duration
  , isGrain
  , isNatural
  , minutesFromHourMixedFraction
  , nPlusOneHalf
  , secondsFromHourMixedFraction
  , timesOneQuarter
  , timesThreeQuarter
  ) where

import Prelude

import Duckling.Dimensions.Types
import Duckling.Duration.Types (DurationData (DurationData))
import Duckling.Numeral.Helpers (isNatural)
import Duckling.Types
import qualified Duckling.Duration.Types as TDuration
import qualified Duckling.TimeGrain.Types as TG

-- -----------------------------------------------------------------
-- Patterns

isGrain :: TG.Grain -> Predicate
isGrain :: Grain -> Predicate
isGrain Grain
value (Token Dimension a
TimeGrain a
grain) = a
grain a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
Grain
value
isGrain Grain
_ Token
_ = Bool
False

-- -----------------------------------------------------------------
-- Production

duration :: TG.Grain -> Int -> DurationData
duration :: Grain -> Int -> DurationData
duration Grain
grain Int
n = DurationData :: Int -> Grain -> DurationData
DurationData {grain :: Grain
TDuration.grain = Grain
grain, value :: Int
TDuration.value = Int
n}

minutesFromHourMixedFraction :: Integer -> Integer -> Integer -> DurationData
minutesFromHourMixedFraction :: Integer -> Integer -> Integer -> DurationData
minutesFromHourMixedFraction Integer
h Integer
n Integer
d =
  Grain -> Int -> DurationData
duration Grain
TG.Minute (Int -> DurationData) -> Int -> DurationData
forall a b. (a -> b) -> a -> b
$ Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> Int) -> Integer -> Int
forall a b. (a -> b) -> a -> b
$ Integer
60 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
h Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
quot (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
60) Integer
d

nPlusOneHalf :: TG.Grain -> Int -> Maybe DurationData
nPlusOneHalf :: Grain -> Int -> Maybe DurationData
nPlusOneHalf Grain
grain = case Grain
grain of
  Grain
TG.Minute -> DurationData -> Maybe DurationData
forall a. a -> Maybe a
Just (DurationData -> Maybe DurationData)
-> (Int -> DurationData) -> Int -> Maybe DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Grain -> Int -> DurationData
duration Grain
TG.Second (Int -> DurationData) -> (Int -> Int) -> Int -> DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
30Int -> Int -> Int
forall a. Num a => a -> a -> a
+) (Int -> Int) -> (Int -> Int) -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
60Int -> Int -> Int
forall a. Num a => a -> a -> a
*)
  Grain
TG.Hour   -> DurationData -> Maybe DurationData
forall a. a -> Maybe a
Just (DurationData -> Maybe DurationData)
-> (Int -> DurationData) -> Int -> Maybe DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Grain -> Int -> DurationData
duration Grain
TG.Minute (Int -> DurationData) -> (Int -> Int) -> Int -> DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
30Int -> Int -> Int
forall a. Num a => a -> a -> a
+) (Int -> Int) -> (Int -> Int) -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
60Int -> Int -> Int
forall a. Num a => a -> a -> a
*)
  Grain
TG.Day    -> DurationData -> Maybe DurationData
forall a. a -> Maybe a
Just (DurationData -> Maybe DurationData)
-> (Int -> DurationData) -> Int -> Maybe DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Grain -> Int -> DurationData
duration Grain
TG.Hour   (Int -> DurationData) -> (Int -> Int) -> Int -> DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
12Int -> Int -> Int
forall a. Num a => a -> a -> a
+) (Int -> Int) -> (Int -> Int) -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
24Int -> Int -> Int
forall a. Num a => a -> a -> a
*)
  Grain
TG.Month  -> DurationData -> Maybe DurationData
forall a. a -> Maybe a
Just (DurationData -> Maybe DurationData)
-> (Int -> DurationData) -> Int -> Maybe DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Grain -> Int -> DurationData
duration Grain
TG.Day    (Int -> DurationData) -> (Int -> Int) -> Int -> DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
15Int -> Int -> Int
forall a. Num a => a -> a -> a
+) (Int -> Int) -> (Int -> Int) -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
30Int -> Int -> Int
forall a. Num a => a -> a -> a
*)
  Grain
TG.Year   -> DurationData -> Maybe DurationData
forall a. a -> Maybe a
Just (DurationData -> Maybe DurationData)
-> (Int -> DurationData) -> Int -> Maybe DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Grain -> Int -> DurationData
duration Grain
TG.Month  (Int -> DurationData) -> (Int -> Int) -> Int -> DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
6Int -> Int -> Int
forall a. Num a => a -> a -> a
+)  (Int -> Int) -> (Int -> Int) -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
12Int -> Int -> Int
forall a. Num a => a -> a -> a
*)
  Grain
_         -> Maybe DurationData -> Int -> Maybe DurationData
forall a b. a -> b -> a
const Maybe DurationData
forall a. Maybe a
Nothing

secondsFromHourMixedFraction :: Integer -> Integer -> Integer -> DurationData
secondsFromHourMixedFraction :: Integer -> Integer -> Integer -> DurationData
secondsFromHourMixedFraction Integer
m Integer
s Integer
d =
  Grain -> Int -> DurationData
duration Grain
TG.Second (Int -> DurationData) -> Int -> DurationData
forall a b. (a -> b) -> a -> b
$ Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> Int) -> Integer -> Int
forall a b. (a -> b) -> a -> b
$ Integer
60 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
m Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
quot (Integer
s Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
60) Integer
d

timesOneQuarter :: TG.Grain -> Int -> Maybe DurationData
timesOneQuarter :: Grain -> Int -> Maybe DurationData
timesOneQuarter Grain
grain = case Grain
grain of
  Grain
TG.Minute -> DurationData -> Maybe DurationData
forall a. a -> Maybe a
Just (DurationData -> Maybe DurationData)
-> (Int -> DurationData) -> Int -> Maybe DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Grain -> Int -> DurationData
duration Grain
TG.Second (Int -> DurationData) -> (Int -> Int) -> Int -> DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
15Int -> Int -> Int
forall a. Num a => a -> a -> a
+) (Int -> Int) -> (Int -> Int) -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
60Int -> Int -> Int
forall a. Num a => a -> a -> a
*)
  Grain
TG.Hour   -> DurationData -> Maybe DurationData
forall a. a -> Maybe a
Just (DurationData -> Maybe DurationData)
-> (Int -> DurationData) -> Int -> Maybe DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Grain -> Int -> DurationData
duration Grain
TG.Minute (Int -> DurationData) -> (Int -> Int) -> Int -> DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
15Int -> Int -> Int
forall a. Num a => a -> a -> a
+) (Int -> Int) -> (Int -> Int) -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
60Int -> Int -> Int
forall a. Num a => a -> a -> a
*)
  Grain
TG.Day    -> DurationData -> Maybe DurationData
forall a. a -> Maybe a
Just (DurationData -> Maybe DurationData)
-> (Int -> DurationData) -> Int -> Maybe DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Grain -> Int -> DurationData
duration Grain
TG.Hour   (Int -> DurationData) -> (Int -> Int) -> Int -> DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
6Int -> Int -> Int
forall a. Num a => a -> a -> a
+) (Int -> Int) -> (Int -> Int) -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
24Int -> Int -> Int
forall a. Num a => a -> a -> a
*)
  Grain
TG.Month  -> DurationData -> Maybe DurationData
forall a. a -> Maybe a
Just (DurationData -> Maybe DurationData)
-> (Int -> DurationData) -> Int -> Maybe DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Grain -> Int -> DurationData
duration Grain
TG.Day    (Int -> DurationData) -> (Int -> Int) -> Int -> DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
7Int -> Int -> Int
forall a. Num a => a -> a -> a
+) (Int -> Int) -> (Int -> Int) -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
30Int -> Int -> Int
forall a. Num a => a -> a -> a
*)
  Grain
TG.Year   -> DurationData -> Maybe DurationData
forall a. a -> Maybe a
Just (DurationData -> Maybe DurationData)
-> (Int -> DurationData) -> Int -> Maybe DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Grain -> Int -> DurationData
duration Grain
TG.Month  (Int -> DurationData) -> (Int -> Int) -> Int -> DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
3Int -> Int -> Int
forall a. Num a => a -> a -> a
+)  (Int -> Int) -> (Int -> Int) -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
12Int -> Int -> Int
forall a. Num a => a -> a -> a
*)
  Grain
_         -> Maybe DurationData -> Int -> Maybe DurationData
forall a b. a -> b -> a
const Maybe DurationData
forall a. Maybe a
Nothing

timesThreeQuarter :: TG.Grain -> Int -> Maybe DurationData
timesThreeQuarter :: Grain -> Int -> Maybe DurationData
timesThreeQuarter Grain
grain = case Grain
grain of
  Grain
TG.Minute -> DurationData -> Maybe DurationData
forall a. a -> Maybe a
Just (DurationData -> Maybe DurationData)
-> (Int -> DurationData) -> Int -> Maybe DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Grain -> Int -> DurationData
duration Grain
TG.Second (Int -> DurationData) -> (Int -> Int) -> Int -> DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
45Int -> Int -> Int
forall a. Num a => a -> a -> a
+) (Int -> Int) -> (Int -> Int) -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
60Int -> Int -> Int
forall a. Num a => a -> a -> a
*)
  Grain
TG.Hour   -> DurationData -> Maybe DurationData
forall a. a -> Maybe a
Just (DurationData -> Maybe DurationData)
-> (Int -> DurationData) -> Int -> Maybe DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Grain -> Int -> DurationData
duration Grain
TG.Minute (Int -> DurationData) -> (Int -> Int) -> Int -> DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
45Int -> Int -> Int
forall a. Num a => a -> a -> a
+) (Int -> Int) -> (Int -> Int) -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
60Int -> Int -> Int
forall a. Num a => a -> a -> a
*)
  Grain
TG.Day    -> DurationData -> Maybe DurationData
forall a. a -> Maybe a
Just (DurationData -> Maybe DurationData)
-> (Int -> DurationData) -> Int -> Maybe DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Grain -> Int -> DurationData
duration Grain
TG.Hour   (Int -> DurationData) -> (Int -> Int) -> Int -> DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
18Int -> Int -> Int
forall a. Num a => a -> a -> a
+) (Int -> Int) -> (Int -> Int) -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
24Int -> Int -> Int
forall a. Num a => a -> a -> a
*)
  Grain
TG.Month  -> DurationData -> Maybe DurationData
forall a. a -> Maybe a
Just (DurationData -> Maybe DurationData)
-> (Int -> DurationData) -> Int -> Maybe DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Grain -> Int -> DurationData
duration Grain
TG.Day    (Int -> DurationData) -> (Int -> Int) -> Int -> DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
21Int -> Int -> Int
forall a. Num a => a -> a -> a
+) (Int -> Int) -> (Int -> Int) -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
30Int -> Int -> Int
forall a. Num a => a -> a -> a
*)
  Grain
TG.Year   -> DurationData -> Maybe DurationData
forall a. a -> Maybe a
Just (DurationData -> Maybe DurationData)
-> (Int -> DurationData) -> Int -> Maybe DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Grain -> Int -> DurationData
duration Grain
TG.Month  (Int -> DurationData) -> (Int -> Int) -> Int -> DurationData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
9Int -> Int -> Int
forall a. Num a => a -> a -> a
+)  (Int -> Int) -> (Int -> Int) -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
12Int -> Int -> Int
forall a. Num a => a -> a -> a
*)
  Grain
_         -> Maybe DurationData -> Int -> Maybe DurationData
forall a b. a -> b -> a
const Maybe DurationData
forall a. Maybe a
Nothing