module Test.Gibberish.Gen
  ( trigraph,
    digram,
    unigram,
    frequencies,
    frequency,
    word,
    genPasswordOpts,
    genPassphraseOpts,
    stdGen,
  ) where

import Data.Gibberish.Types

import Control.Monad.Random (StdGen (), mkStdGen)
import Data.Text (Text ())
import Hedgehog
import Hedgehog.Gen qualified as Gen
import Hedgehog.Range qualified as Range

trigraph :: Gen Trigraph
trigraph :: Gen Trigraph
trigraph = do
  Map Digram Frequencies -> Trigraph
Trigraph (Map Digram Frequencies -> Trigraph)
-> GenT Identity (Map Digram Frequencies) -> Gen Trigraph
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Range Int
-> GenT Identity (Digram, Frequencies)
-> GenT Identity (Map Digram Frequencies)
forall (m :: * -> *) k v.
(MonadGen m, Ord k) =>
Range Int -> m (k, v) -> m (Map k v)
Gen.map (Int -> Int -> Range Int
forall a. Integral a => a -> a -> Range a
Range.linear Int
0 Int
250) GenT Identity (Digram, Frequencies)
kv
  where
    kv :: GenT Identity (Digram, Frequencies)
kv = (,) (Digram -> Frequencies -> (Digram, Frequencies))
-> GenT Identity Digram
-> GenT Identity (Frequencies -> (Digram, Frequencies))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenT Identity Digram
digram GenT Identity (Frequencies -> (Digram, Frequencies))
-> GenT Identity Frequencies -> GenT Identity (Digram, Frequencies)
forall a b.
GenT Identity (a -> b) -> GenT Identity a -> GenT Identity b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> GenT Identity Frequencies
frequencies

digram :: Gen Digram
digram :: GenT Identity Digram
digram = Char -> Char -> Digram
Digram (Char -> Char -> Digram)
-> GenT Identity Char -> GenT Identity (Char -> Digram)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenT Identity Char
forall (m :: * -> *). MonadGen m => m Char
Gen.unicode GenT Identity (Char -> Digram)
-> GenT Identity Char -> GenT Identity Digram
forall a b.
GenT Identity (a -> b) -> GenT Identity a -> GenT Identity b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> GenT Identity Char
forall (m :: * -> *). MonadGen m => m Char
Gen.unicode

unigram :: Gen Unigram
unigram :: Gen Unigram
unigram = Char -> Unigram
Unigram (Char -> Unigram) -> GenT Identity Char -> Gen Unigram
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenT Identity Char
forall (m :: * -> *). MonadGen m => m Char
Gen.unicode

frequencies :: Gen Frequencies
frequencies :: GenT Identity Frequencies
frequencies =
  Map Unigram Frequency -> Frequencies
Frequencies
    (Map Unigram Frequency -> Frequencies)
-> GenT Identity (Map Unigram Frequency)
-> GenT Identity Frequencies
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Range Int
-> GenT Identity (Unigram, Frequency)
-> GenT Identity (Map Unigram Frequency)
forall (m :: * -> *) k v.
(MonadGen m, Ord k) =>
Range Int -> m (k, v) -> m (Map k v)
Gen.map (Int -> Int -> Range Int
forall a. Integral a => a -> a -> Range a
Range.linear Int
0 Int
25) GenT Identity (Unigram, Frequency)
kv
  where
    kv :: GenT Identity (Unigram, Frequency)
kv = (,) (Unigram -> Frequency -> (Unigram, Frequency))
-> Gen Unigram -> GenT Identity (Frequency -> (Unigram, Frequency))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Unigram
unigram GenT Identity (Frequency -> (Unigram, Frequency))
-> GenT Identity Frequency -> GenT Identity (Unigram, Frequency)
forall a b.
GenT Identity (a -> b) -> GenT Identity a -> GenT Identity b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> GenT Identity Frequency
frequency

frequency :: Gen Frequency
frequency :: GenT Identity Frequency
frequency = Int -> Frequency
Frequency (Int -> Frequency) -> GenT Identity Int -> GenT Identity Frequency
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Range Int -> GenT Identity Int
forall (m :: * -> *). MonadGen m => Range Int -> m Int
Gen.int (Int -> Int -> Range Int
forall a. Integral a => a -> a -> Range a
Range.linear Int
0 Int
forall a. Bounded a => a
maxBound)

word :: Gen Text
word :: Gen Text
word = Range Int -> GenT Identity Char -> Gen Text
forall (m :: * -> *). MonadGen m => Range Int -> m Char -> m Text
Gen.text (Int -> Int -> Range Int
forall a. Integral a => a -> a -> Range a
Range.linear Int
3 Int
30) (GenT Identity Char -> Gen Text) -> GenT Identity Char -> Gen Text
forall a b. (a -> b) -> a -> b
$ Char -> Char -> GenT Identity Char
forall (m :: * -> *) a. (MonadGen m, Enum a) => a -> a -> m a
Gen.enum Char
'a' Char
'e'

genPasswordOpts :: Gen GenPasswordOpts
genPasswordOpts :: Gen GenPasswordOpts
genPasswordOpts =
  Bool -> Bool -> Bool -> Trigraph -> Int -> GenPasswordOpts
GenPasswordOpts
    (Bool -> Bool -> Bool -> Trigraph -> Int -> GenPasswordOpts)
-> GenT Identity Bool
-> GenT
     Identity (Bool -> Bool -> Trigraph -> Int -> GenPasswordOpts)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenT Identity Bool
forall (m :: * -> *). MonadGen m => m Bool
Gen.bool
    GenT Identity (Bool -> Bool -> Trigraph -> Int -> GenPasswordOpts)
-> GenT Identity Bool
-> GenT Identity (Bool -> Trigraph -> Int -> GenPasswordOpts)
forall a b.
GenT Identity (a -> b) -> GenT Identity a -> GenT Identity b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> GenT Identity Bool
forall (m :: * -> *). MonadGen m => m Bool
Gen.bool
    GenT Identity (Bool -> Trigraph -> Int -> GenPasswordOpts)
-> GenT Identity Bool
-> GenT Identity (Trigraph -> Int -> GenPasswordOpts)
forall a b.
GenT Identity (a -> b) -> GenT Identity a -> GenT Identity b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> GenT Identity Bool
forall (m :: * -> *). MonadGen m => m Bool
Gen.bool
    GenT Identity (Trigraph -> Int -> GenPasswordOpts)
-> Gen Trigraph -> GenT Identity (Int -> GenPasswordOpts)
forall a b.
GenT Identity (a -> b) -> GenT Identity a -> GenT Identity b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen Trigraph
trigraph
    GenT Identity (Int -> GenPasswordOpts)
-> GenT Identity Int -> Gen GenPasswordOpts
forall a b.
GenT Identity (a -> b) -> GenT Identity a -> GenT Identity b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Range Int -> GenT Identity Int
forall (m :: * -> *). MonadGen m => Range Int -> m Int
Gen.int (Int -> Int -> Range Int
forall a. Integral a => a -> a -> Range a
Range.linear Int
0 Int
15)

genPassphraseOpts :: Gen GenPassphraseOpts
genPassphraseOpts :: Gen GenPassphraseOpts
genPassphraseOpts = do
  Int
minLen <- Range Int -> GenT Identity Int
forall (m :: * -> *). MonadGen m => Range Int -> m Int
Gen.int (Int -> Int -> Range Int
forall a. Integral a => a -> a -> Range a
Range.linear Int
0 Int
10)
  Int
maxLen <- Range Int -> GenT Identity Int
forall (m :: * -> *). MonadGen m => Range Int -> m Int
Gen.int (Int -> Int -> Range Int
forall a. Integral a => a -> a -> Range a
Range.linear Int
minLen Int
15)

  Bool -> Bool -> Bool -> Trigraph -> Int -> Int -> GenPassphraseOpts
GenPassphraseOpts
    (Bool
 -> Bool -> Bool -> Trigraph -> Int -> Int -> GenPassphraseOpts)
-> GenT Identity Bool
-> GenT
     Identity
     (Bool -> Bool -> Trigraph -> Int -> Int -> GenPassphraseOpts)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenT Identity Bool
forall (m :: * -> *). MonadGen m => m Bool
Gen.bool
    GenT
  Identity
  (Bool -> Bool -> Trigraph -> Int -> Int -> GenPassphraseOpts)
-> GenT Identity Bool
-> GenT
     Identity (Bool -> Trigraph -> Int -> Int -> GenPassphraseOpts)
forall a b.
GenT Identity (a -> b) -> GenT Identity a -> GenT Identity b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> GenT Identity Bool
forall (m :: * -> *). MonadGen m => m Bool
Gen.bool
    GenT Identity (Bool -> Trigraph -> Int -> Int -> GenPassphraseOpts)
-> GenT Identity Bool
-> GenT Identity (Trigraph -> Int -> Int -> GenPassphraseOpts)
forall a b.
GenT Identity (a -> b) -> GenT Identity a -> GenT Identity b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> GenT Identity Bool
forall (m :: * -> *). MonadGen m => m Bool
Gen.bool
    GenT Identity (Trigraph -> Int -> Int -> GenPassphraseOpts)
-> Gen Trigraph -> GenT Identity (Int -> Int -> GenPassphraseOpts)
forall a b.
GenT Identity (a -> b) -> GenT Identity a -> GenT Identity b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen Trigraph
trigraph
    GenT Identity (Int -> Int -> GenPassphraseOpts)
-> GenT Identity Int -> GenT Identity (Int -> GenPassphraseOpts)
forall a b.
GenT Identity (a -> b) -> GenT Identity a -> GenT Identity b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> GenT Identity Int
forall a. a -> GenT Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
minLen
    GenT Identity (Int -> GenPassphraseOpts)
-> GenT Identity Int -> Gen GenPassphraseOpts
forall a b.
GenT Identity (a -> b) -> GenT Identity a -> GenT Identity b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> GenT Identity Int
forall a. a -> GenT Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
maxLen

stdGen :: Gen StdGen
stdGen :: Gen StdGen
stdGen = Int -> StdGen
mkStdGen (Int -> StdGen) -> GenT Identity Int -> Gen StdGen
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Range Int -> GenT Identity Int
forall (m :: * -> *) a. (MonadGen m, Integral a) => Range a -> m a
Gen.integral (Int -> Int -> Range Int
forall a. Integral a => a -> a -> Range a
Range.linear Int
forall a. Bounded a => a
minBound Int
forall a. Bounded a => a
maxBound)