-- 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. An additional grant
-- of patent rights can be found in the PATENTS file in the same directory.


{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}

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

import Control.Monad (join)
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

ruleOrdinalsFirstth :: Rule
ruleOrdinalsFirstth = Rule
  { name = "ordinals (first..19th)"
  , pattern =
    [ regex "(перв|втор|трет|четверт|пят|шест|седьм|восьм|девят|десят|одинадцат|двенадцат|тринадцат|четырнадцат|пятнадцат|шестнадцат|семнадцат|восемнадцат|девятнадцат|двадцат)(ый|ой|ий|ая|ое)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) -> case match of
        "перв" -> Just $ ordinal 1
        "втор" -> Just $ ordinal 2
        "трет" -> Just $ ordinal 3
        "четверт" -> Just $ ordinal 4
        "пят" -> Just $ ordinal 5
        "шест" -> Just $ ordinal 6
        "седьм" -> Just $ ordinal 7
        "восьм" -> Just $ ordinal 8
        "девят" -> Just $ ordinal 9
        "десят" -> Just $ ordinal 10
        "одинадцат" -> Just $ ordinal 11
        "двенадцат" -> Just $ ordinal 12
        "тринадцат" -> Just $ ordinal 13
        "четырнадцат" -> Just $ ordinal 14
        "пятнадцат" -> Just $ ordinal 15
        "шестнадцат" -> Just $ ordinal 16
        "семнадцат" -> Just $ ordinal 17
        "восемнадцат" -> Just $ ordinal 18
        "девятнадцат" -> Just $ ordinal 19
        "двадцат" -> Just $ ordinal 20
        _ -> Nothing
      _ -> Nothing
  }

ruleOrdinal :: Rule
ruleOrdinal = Rule
  { name = "ordinal 21..99"
  , pattern =
    [ regex "(двадцать|тридцать|сорок|пятьдесят|шестьдесят|семьдесят|восемьдесят|девяносто)"
    , regex "(перв|втор|трет|четверт|пят|шест|седьм|восьм|девят)(ый|ой|ий|ая|ое)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (m1:_)):
       Token RegexMatch (GroupMatch (m2:_)):
       _) -> do
         dozen <- case Text.toLower m1 of
           "двадцать" -> Just 20
           "тридцать" -> Just 30
           "сорок" -> Just 40
           "пятьдесят" -> Just 50
           "шестьдесят" -> Just 60
           "семьдесят" -> Just 70
           "восемьдесят" -> Just 80
           "девяносто" -> Just 90
           _ -> Nothing
         unit <- case Text.toLower m2 of
           "перв" -> Just 1
           "втор" -> Just 2
           "трет" -> Just 3
           "четверт" -> Just 4
           "пят" -> Just 5
           "шест" -> Just 6
           "седьм" -> Just 7
           "восьм" -> Just 8
           "девят" -> Just 9
           _ -> Nothing
         Just . ordinal $ dozen + unit
      _ -> Nothing
  }

ruleOrdinalDigits :: Rule
ruleOrdinalDigits = Rule
  { name = "ordinal (digits)"
  , pattern =
    [ regex "0*(\\d+)-?((ы|о|и)?й|ая|ое)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleOrdinal
  , ruleOrdinalDigits
  , ruleOrdinalsFirstth
  ]