{-# LANGUAGE CPP                        #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Fake.Provider.Lang
  ( SingleWord(..)
  , capitalize
  , lowerize
  , Phrase
  , phrase
  , phraseText
  ) where

import           Data.Bifunctor
#if MIN_VERSION_base(4,11,0)
import           Data.Semigroup
#endif
import           Data.String
import           Data.Text (Text)
import qualified Data.Text as T
import           Fake.Types

------------------------------------------------------------------------------
-- | Newtype wrapper representing a single word.
newtype SingleWord = SingleWord { SingleWord -> Text
unSingleWord :: Text }
#if MIN_VERSION_base(4,11,0)
  deriving (SingleWord -> SingleWord -> Bool
(SingleWord -> SingleWord -> Bool)
-> (SingleWord -> SingleWord -> Bool) -> Eq SingleWord
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SingleWord -> SingleWord -> Bool
$c/= :: SingleWord -> SingleWord -> Bool
== :: SingleWord -> SingleWord -> Bool
$c== :: SingleWord -> SingleWord -> Bool
Eq,Eq SingleWord
Eq SingleWord
-> (SingleWord -> SingleWord -> Ordering)
-> (SingleWord -> SingleWord -> Bool)
-> (SingleWord -> SingleWord -> Bool)
-> (SingleWord -> SingleWord -> Bool)
-> (SingleWord -> SingleWord -> Bool)
-> (SingleWord -> SingleWord -> SingleWord)
-> (SingleWord -> SingleWord -> SingleWord)
-> Ord SingleWord
SingleWord -> SingleWord -> Bool
SingleWord -> SingleWord -> Ordering
SingleWord -> SingleWord -> SingleWord
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: SingleWord -> SingleWord -> SingleWord
$cmin :: SingleWord -> SingleWord -> SingleWord
max :: SingleWord -> SingleWord -> SingleWord
$cmax :: SingleWord -> SingleWord -> SingleWord
>= :: SingleWord -> SingleWord -> Bool
$c>= :: SingleWord -> SingleWord -> Bool
> :: SingleWord -> SingleWord -> Bool
$c> :: SingleWord -> SingleWord -> Bool
<= :: SingleWord -> SingleWord -> Bool
$c<= :: SingleWord -> SingleWord -> Bool
< :: SingleWord -> SingleWord -> Bool
$c< :: SingleWord -> SingleWord -> Bool
compare :: SingleWord -> SingleWord -> Ordering
$ccompare :: SingleWord -> SingleWord -> Ordering
$cp1Ord :: Eq SingleWord
Ord,Int -> SingleWord -> ShowS
[SingleWord] -> ShowS
SingleWord -> String
(Int -> SingleWord -> ShowS)
-> (SingleWord -> String)
-> ([SingleWord] -> ShowS)
-> Show SingleWord
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SingleWord] -> ShowS
$cshowList :: [SingleWord] -> ShowS
show :: SingleWord -> String
$cshow :: SingleWord -> String
showsPrec :: Int -> SingleWord -> ShowS
$cshowsPrec :: Int -> SingleWord -> ShowS
Show,b -> SingleWord -> SingleWord
NonEmpty SingleWord -> SingleWord
SingleWord -> SingleWord -> SingleWord
(SingleWord -> SingleWord -> SingleWord)
-> (NonEmpty SingleWord -> SingleWord)
-> (forall b. Integral b => b -> SingleWord -> SingleWord)
-> Semigroup SingleWord
forall b. Integral b => b -> SingleWord -> SingleWord
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: b -> SingleWord -> SingleWord
$cstimes :: forall b. Integral b => b -> SingleWord -> SingleWord
sconcat :: NonEmpty SingleWord -> SingleWord
$csconcat :: NonEmpty SingleWord -> SingleWord
<> :: SingleWord -> SingleWord -> SingleWord
$c<> :: SingleWord -> SingleWord -> SingleWord
Semigroup,Semigroup SingleWord
SingleWord
Semigroup SingleWord
-> SingleWord
-> (SingleWord -> SingleWord -> SingleWord)
-> ([SingleWord] -> SingleWord)
-> Monoid SingleWord
[SingleWord] -> SingleWord
SingleWord -> SingleWord -> SingleWord
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [SingleWord] -> SingleWord
$cmconcat :: [SingleWord] -> SingleWord
mappend :: SingleWord -> SingleWord -> SingleWord
$cmappend :: SingleWord -> SingleWord -> SingleWord
mempty :: SingleWord
$cmempty :: SingleWord
$cp1Monoid :: Semigroup SingleWord
Monoid,String -> SingleWord
(String -> SingleWord) -> IsString SingleWord
forall a. (String -> a) -> IsString a
fromString :: String -> SingleWord
$cfromString :: String -> SingleWord
IsString)
#else
  deriving (Eq,Ord,Show,Monoid,IsString)
#endif

capitalize :: SingleWord -> SingleWord
capitalize :: SingleWord -> SingleWord
capitalize = Text -> SingleWord
SingleWord (Text -> SingleWord)
-> (SingleWord -> Text) -> SingleWord -> SingleWord
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
             (Text -> Text -> Text) -> (Text, Text) -> Text
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Text -> Text -> Text
forall a. Monoid a => a -> a -> a
mappend ((Text, Text) -> Text)
-> (SingleWord -> (Text, Text)) -> SingleWord -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Text) -> (Text, Text) -> (Text, Text)
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first Text -> Text
T.toUpper ((Text, Text) -> (Text, Text))
-> (SingleWord -> (Text, Text)) -> SingleWord -> (Text, Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Text -> (Text, Text)
T.splitAt Int
1 (Text -> (Text, Text))
-> (SingleWord -> Text) -> SingleWord -> (Text, Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SingleWord -> Text
unSingleWord

lowerize :: SingleWord -> SingleWord
lowerize :: SingleWord -> SingleWord
lowerize = Text -> SingleWord
SingleWord (Text -> SingleWord)
-> (SingleWord -> Text) -> SingleWord -> SingleWord
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
           (Text -> Text -> Text) -> (Text, Text) -> Text
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Text -> Text -> Text
forall a. Monoid a => a -> a -> a
mappend ((Text, Text) -> Text)
-> (SingleWord -> (Text, Text)) -> SingleWord -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Text) -> (Text, Text) -> (Text, Text)
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first Text -> Text
T.toLower ((Text, Text) -> (Text, Text))
-> (SingleWord -> (Text, Text)) -> SingleWord -> (Text, Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Text -> (Text, Text)
T.splitAt Int
1 (Text -> (Text, Text))
-> (SingleWord -> Text) -> SingleWord -> (Text, Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SingleWord -> Text
unSingleWord

------------------------------------------------------------------------------
newtype Phrase = Phrase { Phrase -> [SingleWord]
unPhrase :: [SingleWord] }
#if MIN_VERSION_base(4,11,0)
  deriving (Phrase -> Phrase -> Bool
(Phrase -> Phrase -> Bool)
-> (Phrase -> Phrase -> Bool) -> Eq Phrase
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Phrase -> Phrase -> Bool
$c/= :: Phrase -> Phrase -> Bool
== :: Phrase -> Phrase -> Bool
$c== :: Phrase -> Phrase -> Bool
Eq,Eq Phrase
Eq Phrase
-> (Phrase -> Phrase -> Ordering)
-> (Phrase -> Phrase -> Bool)
-> (Phrase -> Phrase -> Bool)
-> (Phrase -> Phrase -> Bool)
-> (Phrase -> Phrase -> Bool)
-> (Phrase -> Phrase -> Phrase)
-> (Phrase -> Phrase -> Phrase)
-> Ord Phrase
Phrase -> Phrase -> Bool
Phrase -> Phrase -> Ordering
Phrase -> Phrase -> Phrase
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Phrase -> Phrase -> Phrase
$cmin :: Phrase -> Phrase -> Phrase
max :: Phrase -> Phrase -> Phrase
$cmax :: Phrase -> Phrase -> Phrase
>= :: Phrase -> Phrase -> Bool
$c>= :: Phrase -> Phrase -> Bool
> :: Phrase -> Phrase -> Bool
$c> :: Phrase -> Phrase -> Bool
<= :: Phrase -> Phrase -> Bool
$c<= :: Phrase -> Phrase -> Bool
< :: Phrase -> Phrase -> Bool
$c< :: Phrase -> Phrase -> Bool
compare :: Phrase -> Phrase -> Ordering
$ccompare :: Phrase -> Phrase -> Ordering
$cp1Ord :: Eq Phrase
Ord,Int -> Phrase -> ShowS
[Phrase] -> ShowS
Phrase -> String
(Int -> Phrase -> ShowS)
-> (Phrase -> String) -> ([Phrase] -> ShowS) -> Show Phrase
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Phrase] -> ShowS
$cshowList :: [Phrase] -> ShowS
show :: Phrase -> String
$cshow :: Phrase -> String
showsPrec :: Int -> Phrase -> ShowS
$cshowsPrec :: Int -> Phrase -> ShowS
Show,b -> Phrase -> Phrase
NonEmpty Phrase -> Phrase
Phrase -> Phrase -> Phrase
(Phrase -> Phrase -> Phrase)
-> (NonEmpty Phrase -> Phrase)
-> (forall b. Integral b => b -> Phrase -> Phrase)
-> Semigroup Phrase
forall b. Integral b => b -> Phrase -> Phrase
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: b -> Phrase -> Phrase
$cstimes :: forall b. Integral b => b -> Phrase -> Phrase
sconcat :: NonEmpty Phrase -> Phrase
$csconcat :: NonEmpty Phrase -> Phrase
<> :: Phrase -> Phrase -> Phrase
$c<> :: Phrase -> Phrase -> Phrase
Semigroup,Semigroup Phrase
Phrase
Semigroup Phrase
-> Phrase
-> (Phrase -> Phrase -> Phrase)
-> ([Phrase] -> Phrase)
-> Monoid Phrase
[Phrase] -> Phrase
Phrase -> Phrase -> Phrase
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [Phrase] -> Phrase
$cmconcat :: [Phrase] -> Phrase
mappend :: Phrase -> Phrase -> Phrase
$cmappend :: Phrase -> Phrase -> Phrase
mempty :: Phrase
$cmempty :: Phrase
$cp1Monoid :: Semigroup Phrase
Monoid)
#else
  deriving (Eq,Ord,Show,Monoid)
#endif

phraseText :: Phrase -> Text
phraseText :: Phrase -> Text
phraseText = [Text] -> Text
T.unwords ([Text] -> Text) -> (Phrase -> [Text]) -> Phrase -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SingleWord -> Text) -> [SingleWord] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map SingleWord -> Text
unSingleWord ([SingleWord] -> [Text])
-> (Phrase -> [SingleWord]) -> Phrase -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Phrase -> [SingleWord]
unPhrase

phrase :: [FGen SingleWord] -> FGen Phrase
phrase :: [FGen SingleWord] -> FGen Phrase
phrase = ([SingleWord] -> Phrase) -> FGen [SingleWord] -> FGen Phrase
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [SingleWord] -> Phrase
Phrase (FGen [SingleWord] -> FGen Phrase)
-> ([FGen SingleWord] -> FGen [SingleWord])
-> [FGen SingleWord]
-> FGen Phrase
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FGen SingleWord] -> FGen [SingleWord]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence