-- 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 #-}
{-# LANGUAGE NoRebindableSyntax #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.EL.Rules
  ( rules ) where

import Data.HashMap.Strict ( HashMap)
import Data.String
import Data.Text (Text)
import Prelude
import qualified Data.HashMap.Strict as HashMap
import qualified Data.Text as Text

import Duckling.Dimensions.Types
import Duckling.Numeral.Helpers (parseInt)
import Duckling.Ordinal.Helpers
import Duckling.Ordinal.Types (OrdinalData (..), isBetween)
import Duckling.Regex.Types
import Duckling.Types
import qualified Duckling.Ordinal.Types as TOrdinal

ordinalsMap :: HashMap Text Int
ordinalsMap :: HashMap Text Int
ordinalsMap = [(Text, Int)] -> HashMap Text Int
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HashMap.fromList
  [ ( Text
"πρώτ"        , Int
1  )
  , ( Text
"δεύτερ"      , Int
2  )
  , ( Text
"δευτέρ"      , Int
2  )
  , ( Text
"τρίτ"        , Int
3  )
  , ( Text
"τέταρτ"      , Int
4  )
  , ( Text
"τετάρτ"      , Int
4  )
  , ( Text
"πέμπτ"       , Int
5  )
  , ( Text
"έκτ"         , Int
6  )
  , ( Text
"έβδομ"       , Int
7  )
  , ( Text
"εβδόμ"       , Int
7  )
  , ( Text
"όγδο"        , Int
8  )
  , ( Text
"ογδό"        , Int
8  )
  , ( Text
"ένατ"        , Int
9  )
  , ( Text
"ενάτ"        , Int
9  )
  , ( Text
"δέκατ"       , Int
10 )
  , ( Text
"δεκάτ"       , Int
10 )
  , ( Text
"ενδέκατ"     , Int
11 )
  , ( Text
"ενδεκάτ"     , Int
11 )
  , ( Text
"δωδέκατ"     , Int
12 )
  , ( Text
"δωδεκάτ"     , Int
12 )
  , ( Text
"εικοστ"      , Int
20 )
  , ( Text
"τριακοστ"    , Int
30 )
  , ( Text
"τεσσαρακοστ" , Int
40 )
  , ( Text
"πεντηκοστ"   , Int
50 )
  , ( Text
"εξηκοστ"     , Int
60 )
  , ( Text
"εβδομηκοστ"  , Int
70 )
  , ( Text
"ογδοηκοστ"   , Int
80 )
  , ( Text
"ενενηκοστ"   , Int
90 )
  ]

ruleOrdinals :: Rule
ruleOrdinals :: Rule
ruleOrdinals = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"ordinals (1st..12th, 20th, 30th..90th)"
  , pattern :: Pattern
pattern =
      [ String -> PatternItem
regex (String -> PatternItem) -> String -> PatternItem
forall a b. (a -> b) -> a -> b
$ String
"(πρώτ|δε[υύ]τ[εέ]ρ|τρίτ|τ[εέ]τ[αά]ρτ|πέμπτ|"
             String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"έκτ|[εέ]βδ[οό]μ(ηκοστ)?|[οό]γδ[οό](ηκοστ)?|[εέ]ν[αά]τ|δ[εέ]κ[αά]τ|"
             String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"εν[δτ][εέ]κ[αά]τ|δωδ[εέ]κ[αά]τ|"
             String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"εικοστ|τριακοστ|τεσσαρακοστ|πεντηκοστ|"
             String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"εξηκοστ|ενενηκοστ)"
             String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"([οό][υύιί]?ς?|[ηή]ς?|[εέ]ς|ων)"
      ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
RegexMatch (GroupMatch (match:_)):[Token]
_) ->
        Int -> Token
ordinal (Int -> Token) -> Maybe Int -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> HashMap Text Int -> Maybe Int
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HashMap.lookup (Text -> Text
Text.toLower Text
match) HashMap Text Int
ordinalsMap
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
    }

ruleCompositeOrdinals :: Rule
ruleCompositeOrdinals :: Rule
ruleCompositeOrdinals = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"ordinals (composite: 11th..19th, 21st..29th, ..., 91st..99th)"
  , pattern :: Pattern
pattern =
      [ [Int] -> PatternItem
oneOf [Int
10..Int
90]
      , [Int] -> PatternItem
oneOf [Int
1..Int
9]
      ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      ( Token Dimension a
Ordinal OrdinalData{TOrdinal.value = t} :
        Token Dimension a
Ordinal OrdinalData{TOrdinal.value = u} : [Token]
_ )
        -> Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token) -> Token -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Int -> Token
ordinal (Int -> Token) -> Int -> Token
forall a b. (a -> b) -> a -> b
$ Int
t Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
u
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleOrdinalDigits :: Rule
ruleOrdinalDigits :: Rule
ruleOrdinalDigits = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"ordinal (digits)"
  , pattern :: Pattern
pattern = [String -> PatternItem
regex String
"0*(\\d+) ?(ο[ςυι]?|ης?|ες)"]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
RegexMatch (GroupMatch (match:_)):[Token]
_) -> Int -> Token
ordinal (Int -> Token) -> Maybe Int -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Maybe Int
parseInt Text
match
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

rules :: [Rule]
rules :: [Rule]
rules =
  [ Rule
ruleOrdinals
  , Rule
ruleCompositeOrdinals
  , Rule
ruleOrdinalDigits
  ]