-- 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.

module Duckling.Time.HolidayHelpers
  ( computeEarthHour, computeKingsDay
  ) where

import Data.Maybe
import Prelude

import Duckling.Time.Helpers
import Duckling.Time.Computed
import Duckling.Time.Types (TimeData (..))
import qualified Duckling.Time.Types as TTime
import qualified Duckling.TimeGrain.Types as TG

-- Last Saturday of March unless it falls on Holy Saturday,
-- in which case it's the Saturday before.
computeEarthHour :: Maybe TimeData
computeEarthHour :: Maybe TimeData
computeEarthHour =
  let holySaturday :: TimeData
holySaturday = Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day (-Int
1) TimeData
easterSunday
      tentative :: TimeData
tentative = TimeData -> TimeData -> TimeData
predLastOf (Int -> TimeData
dayOfWeek Int
6) (Int -> TimeData
month Int
3)
      alternative :: TimeData
alternative = Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day (-Int
7) TimeData
tentative
    in do
      TimeData
day <- TimeData -> TimeData -> TimeData -> Maybe TimeData
intersectWithReplacement TimeData
holySaturday TimeData
tentative TimeData
alternative
      TimeData
start <- TimeData -> TimeData -> Maybe TimeData
intersect TimeData
day (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Bool -> Int -> Int -> TimeData
hourMinute Bool
True Int
20 Int
30
      TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Closed TimeData
start (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Minute Int
60 TimeData
start

-- King's day is on April 27th unless it's on Sunday, in which case it's a day
-- earlier. We intersect with the last Sunday of April. If 4/27 is a Sunday it
-- will be the last Sunday in April.
computeKingsDay :: Maybe TimeData
computeKingsDay :: Maybe TimeData
computeKingsDay =
  let tentative :: TimeData
tentative = Int -> Int -> TimeData
monthDay Int
4 Int
27
      alternative :: TimeData
alternative = Int -> Int -> TimeData
monthDay Int
4 Int
26
      lastSundayOfApril :: TimeData
lastSundayOfApril = TimeData -> TimeData -> TimeData
predLastOf (Int -> TimeData
dayOfWeek Int
7) (Int -> TimeData
month Int
4)
    in TimeData -> TimeData -> TimeData -> Maybe TimeData
intersectWithReplacement TimeData
lastSundayOfApril TimeData
tentative TimeData
alternative