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

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

import Data.HashMap.Strict (HashMap)
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.Regex.Types
import Duckling.Types

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
3 )
  , ( Text
"четвърт"      , Int
4 )
  , ( Text
"пет"          , Int
5 )
  , ( Text
"шест"         , Int
6 )
  , ( Text
"седм"         , Int
7 )
  , ( Text
"осм"          , Int
8 )
  , ( Text
"девет"        , Int
9 )
  , ( Text
"десет"        , Int
10 )
  , ( Text
"единадесет"   , Int
11 )
  , ( Text
"дванадесет"   , Int
12 )
  , ( Text
"тринадесет"   , Int
13 )
  , ( Text
"четиринадесет", Int
14 )
  , ( Text
"петнадесет"   , Int
15 )
  , ( Text
"шестнадесет"  , Int
16 )
  , ( Text
"седемнадесет" , Int
17 )
  , ( Text
"осемнадесет"  , Int
18 )
  , ( Text
"деветнадесет" , Int
19 )
  , ( Text
"двадесет"     , Int
20 )
  ]

ruleOrdinalsFirstth :: Rule
ruleOrdinalsFirstth :: Rule
ruleOrdinalsFirstth = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"ordinals (first..19th)"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex 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
  }

dozensMap :: HashMap Text Int
dozensMap :: HashMap Text Int
dozensMap = [(Text, Int)] -> HashMap Text Int
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HashMap.fromList
  [ ( Text
"двадесет"  , Int
20 )
  , ( Text
"тридесет"  , Int
30 )
  , ( Text
"четирдесет", Int
40 )
  , ( Text
"петдесет"  , Int
50 )
  , ( Text
"шестдесет" , Int
60 )
  , ( Text
"седемдесет", Int
70 )
  , ( Text
"осемдесет" , Int
80 )
  , ( Text
"деветдесет", Int
90 )
  ]

ruleOrdinal :: Rule
ruleOrdinal :: Rule
ruleOrdinal = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"ordinal 21..99"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(двадесет|тридесет|четирдесет|петдесет|шестдесет|седемдесет|осемдесет|деветдесет)"
    , String -> PatternItem
regex String
"и (първ|втор|трет|четвърт|пет|шест|седм|осм|девет)(и(ят?|те)?|а(та)?|о(то)?)"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
RegexMatch (GroupMatch (m1:_)):
       Token Dimension a
RegexMatch (GroupMatch (m2:_)):
       [Token]
_) -> do
         Int
dozen <- 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
m1) HashMap Text Int
dozensMap
         Int
unit <- 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
m2) HashMap Text Int
ordinalsMap
         Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token) -> (Int -> Token) -> Int -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Token
ordinal (Int -> Maybe Token) -> Int -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Int
dozen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
unit
      [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
ruleOrdinal
  , Rule
ruleOrdinalDigits
  , Rule
ruleOrdinalsFirstth
  ]