{-# LANGUAGE NoImplicitPrelude   #-}
{-# LANGUAGE OverloadedStrings   #-}
{-# LANGUAGE PackageImports      #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UnicodeSyntax       #-}

{-|
[@ISO639-1@]        af

[@ISO639-2@]        afr

[@ISO639-3@]        afr

[@Native name@]     Afrikaans

[@English name@]    Afrikaans
-}

module Text.Numeral.Language.AF
    ( -- * Language entry
      entry
      -- * Conversions
    , cardinal
    , ordinal
      -- * Structure
    , struct
      -- * Bounds
    , bounds
    ) where


--------------------------------------------------------------------------------
-- Imports
--------------------------------------------------------------------------------

import "base" Data.Bool     ( otherwise )
import "base" Data.Function ( ($), const, fix )
import "base" Data.Maybe    ( Maybe(Just) )
import "base" Data.Ord      ( (<) )
import "base" Prelude       ( Integral, (-), negate )
import "base-unicode-symbols" Data.Function.Unicode ( () )
import qualified "containers" Data.Map as M ( fromList, lookup )
import           "this" Text.Numeral
import qualified "this" Text.Numeral.BigNum as BN
import qualified "this" Text.Numeral.Exp as E
import           "this" Text.Numeral.Grammar ( Inflection )
import           "this" Text.Numeral.Misc ( dec )
import "this" Text.Numeral.Entry
import "text" Data.Text ( Text )


--------------------------------------------------------------------------------
-- AF
--------------------------------------------------------------------------------

entry  Entry
entry = emptyEntry
    { entIso639_1    = Just "af"
    , entIso639_2    = ["afr"]
    , entIso639_3    = Just "afr"
    , entNativeNames = ["Afrikaans"]
    , entEnglishName = Just "Afrikaans"
    , entCardinal    = Just Conversion
                            { toNumeral   = cardinal
                            , toStructure = struct
                            }
    , entOrdinal     = Just Conversion
                            { toNumeral   = ordinal
                            , toStructure = struct
                            }
    }

cardinal  (Inflection i, Integral α, E.Scale α)  i  α  Maybe Text
cardinal inf = cardinalRepr inf  struct

ordinal  (Inflection i, Integral α, E.Scale α)  i  α  Maybe Text
ordinal inf = ordinalRepr inf  struct

struct  ( Integral α, E.Scale α
         , E.Unknown β, E.Lit β, E.Neg β, E.Add β, E.Mul β, E.Scale β
         )
        α  β
struct = pos
       $ fix
       $ findRule (   0, lit                )
                [ (  13, add     10      L  )
                , (  20, mul     10      L L)
                , ( 100, step1  100   10 R L)
                , (1000, step1 1000 1000 R L)
                ]
                  (dec 6 - 1)
         `combine` pelletierScale1 R L BN.rule

bounds  (Integral α)  (α, α)
bounds = let x = dec 60000 - 1 in (negate x, x)

genericRepr  Repr i
genericRepr = defaultRepr
               { reprAdd   = Just ()
               , reprMul   = Just ()
               , reprNeg   = Just $ \_ _    "min "
               }
    where
      (_      Lit 10) _         = ""
      (Lit n  _) _ | n < 10     = "-en-"
                    | otherwise  = ""
      (_      _) _              = " "

      (_  Lit _) _ = ""
      (_  _    ) _ = " "

cardinalRepr  i  Exp i  Maybe Text
cardinalRepr = render genericRepr
               { reprValue = \_ n  M.lookup n syms
               , reprScale = BN.pelletierRepr (\_ _  "iljoen")
                                              (\_ _  "iljard")
                                              []
               }
    where
      syms =
          M.fromList
          [ (0, const "nul")
          , (1, const "een")
          , (2, forms "twee" "twin")
          , (3, forms "drie" "der")
          , (4, forms "vier" "veer")
          , (5, const "vyf")
          , (6, const "ses")
          , (7, forms "sewe" "sewen")
          , (8, \c  case c of
                       CtxMul _ (Lit 10) _  "tag"
                       _                    "ag"
            )
          , (9, \c  case c of
                       CtxAdd _ (Lit 10) _  "negen"
                       CtxMul _ (Lit 10) _  "neën"
                       _                    "nege"
            )
          , (10, \c  case c of
                        CtxMul R _ _  "tig"
                        _             "tien"
            )
          , (11, const "elf")
          , (12, const "twaalf")
          , (100, const "honderd")
          , (1000, const "duisend")
          ]

      forms  s  s  Ctx (Exp i)  s
      forms n t ctx = case ctx of
                        CtxMul _ (Lit 10) _  t
                        CtxAdd _ (Lit 10) _  t
                        CtxAdd _ (Lit _)  _  n
                        _                    n

ordinalRepr  i  Exp i  Maybe Text
ordinalRepr = render genericRepr
              { reprValue = \_ n  M.lookup n syms
              , reprScale = BN.pelletierRepr (\_ _  "iljoen")
                                             (\_ _  "iljard")
                                             []
              }
    where
      syms =
          M.fromList
          [ (0, const "nul")
          , (1, \c  case c of
                       CtxEmpty           "eerste"
                       _ | isOutside R c  "eende"
                         | otherwise      "een"
            )
          , (2, forms "tweede" "twee" "twin")
          , (3, forms "derde"  "drie" "der")
          , (4, forms "vierde" "vier" "veer")
          , (5, \c  if isOutside R c then "vyfde" else "vyf")
          , (6, \c  if isOutside R c then "sesde" else "ses")
          , (7, forms "sewende" "sewe" "sewen")
          , (8, \c  case c of
                       _ | isOutside R c    "agtste"
                       CtxMul _ (Lit 10) _  "tag"
                       _                    "ag"
            )
          , (9, \c  case c of
                       _ | isOutside R c    "negende"
                       CtxAdd _ (Lit 10) _  "negen"
                       CtxMul _ (Lit 10) _  "neën"
                       _                    "nege"
            )
          , (10, \c  case c of
                        CtxMul R _ _ | isOutside R c  "tigste"
                                     | otherwise      "tig"
                        _            | isOutside R c  "tiende"
                                     | otherwise      "tien"
            )
          , (11, \c  if isOutside R c then "elfde" else "elf")
          , (12, \c  if isOutside R c then "twaalfde" else "twaalf")
          , (100, \c  if isOutside R c then "honderste" else "honderd")
          , (1000, \c  if isOutside R c then "duisendste" else "duisend")
          ]

      forms  s  s  s  Ctx (Exp i)  s
      forms o c t ctx = case ctx of
                          _ | isOutside R ctx  o
                          CtxMul _ (Lit 10) _  t
                          CtxAdd _ (Lit 10) _  t
                          CtxAdd _ (Lit _)  _  c
                          _                    c