{-# LANGUAGE CPP, OverloadedStrings #-}

module Text.Numeral.Language.EN (enShort, enLong) where

import Data.String
import Text.Numeral
import Text.Numeral.Joinable
import Text.Numeral.Pelletier (shortScale, longScale)

#ifdef DO_SPECIALISE
import qualified Data.ByteString as B
import qualified Data.DString    as DS

{-# SPECIALISE enShort :: NumConfig String #-}
{-# SPECIALISE enShort :: NumConfig B.ByteString #-}
{-# SPECIALISE enShort :: NumConfig DS.DString #-}

{-# SPECIALISE enLong :: NumConfig String #-}
{-# SPECIALISE enLong :: NumConfig B.ByteString #-}
{-# SPECIALISE enLong :: NumConfig DS.DString #-}
#endif

enShort :: (IsString s, Joinable s) => NumConfig s
enShort = NumConfig { ncNeg      = enNeg
                    , ncOne      = enOne
                    , ncAdd      = enAdd
                    , ncMul      = enMul
                    , ncCardinal = findSym $ enTable ++ shortScale "illion"
                    }

enLong :: (IsString s, Joinable s) => NumConfig s
enLong = enShort { ncCardinal = findSym $ enTable ++ longScale "illion" "illiard"}

enNeg :: (IsString s, Joinable s) => s -> s
enNeg = ("minus" <+>)

enOne :: (IsString s, Joinable s) => (Integer, s) -> s
enOne (v,  vs) | v >= 100  = "one" <+> vs
               | otherwise = vs

enAdd :: (IsString s, Joinable s) => (Integer, s) -> (Integer, s) -> s
enAdd (x, x') (_, y') | x < 20    = y' <> x'
                      | x < 100   = x' <-> y'
                      | otherwise = x' <+> y'

enMul :: (IsString s, Joinable s) => (Integer, s) -> (Integer, s) -> s
enMul (_, x') (y, y') | y == 10   = x' <> y'
                      | otherwise = x' <+> y'

enTable :: (IsString s, Joinable s) => [NumSymbol s]
enTable = [ term 0    $ const "zero"
          , term 1    $ const "one"
          , term 2    $ tenForms "two"   "twen" "twen"
          , term 3    $ tenForms "three" "thir" "thir"
          , term 4    $ tenForms "four"  "four" "for"
          , term 5    $ tenForms "five"  "fif"  "fif"
          , term 6    $ const "six"
          , term 7    $ const "seven"
          , term 8    $ tenForms "eight" "eigh" "eigh"
          , term 9    $ const "nine"
          , mul  10   $ \ctx -> case ctx of
                                   LA {} -> "teen"
                                   RM {} -> "ty"
                                   _     -> "ten"
          , term 11   $ const "eleven"
          , term 12   $ const "twelve"
          , mul  100  $ const "hundred"
          , mul  1000 $ const "thousand"
          ]