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

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

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

import Duckling.Dimensions.Types
import Duckling.Numeral.Helpers (parseInt)
import Duckling.Ordinal.Helpers
import Duckling.Regex.Types
import Duckling.Types

ordinalsFirstThMap :: HashMap Text Int
ordinalsFirstThMap :: HashMap Text Int
ordinalsFirstThMap = [(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
ordinalsFirstThMap
    [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ordinalTensMap :: HashMap Text Int
ordinalTensMap :: HashMap Text Int
ordinalTensMap = [(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
v1 <- 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
ordinalTensMap
        Int
v2 <- 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
ordinalsFirstThMap -- map to 1..9
        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
v1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
v2
      [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
  ]