{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}

module ROC.ID.Serial
  ( Serial (..)
  , randomSerial
  ) where

import Control.Monad.Random.Class
    ( MonadRandom (..) )
import Data.Vector.Sized
    ( Vector )
import GHC.Generics
    ( Generic )

import ROC.ID.Digit
import ROC.ID.Utilities

import qualified Data.Vector.Sized as V

-- | A 7-digit serial number, as found within an ROC identification number.
--
-- A serial number is unique for a gender and location.
--
-- To generate a random 'Serial' number, use the 'randomSerial' function.
--
newtype Serial = Serial (Vector 7 Digit)
  deriving (Serial -> Serial -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Serial -> Serial -> Bool
$c/= :: Serial -> Serial -> Bool
== :: Serial -> Serial -> Bool
$c== :: Serial -> Serial -> Bool
Eq, forall x. Rep Serial x -> Serial
forall x. Serial -> Rep Serial x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Serial x -> Serial
$cfrom :: forall x. Serial -> Rep Serial x
Generic, Eq Serial
Serial -> Serial -> Bool
Serial -> Serial -> Ordering
Serial -> Serial -> Serial
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 :: Serial -> Serial -> Serial
$cmin :: Serial -> Serial -> Serial
max :: Serial -> Serial -> Serial
$cmax :: Serial -> Serial -> Serial
>= :: Serial -> Serial -> Bool
$c>= :: Serial -> Serial -> Bool
> :: Serial -> Serial -> Bool
$c> :: Serial -> Serial -> Bool
<= :: Serial -> Serial -> Bool
$c<= :: Serial -> Serial -> Bool
< :: Serial -> Serial -> Bool
$c< :: Serial -> Serial -> Bool
compare :: Serial -> Serial -> Ordering
$ccompare :: Serial -> Serial -> Ordering
Ord, Int -> Serial -> ShowS
[Serial] -> ShowS
Serial -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Serial] -> ShowS
$cshowList :: [Serial] -> ShowS
show :: Serial -> String
$cshow :: Serial -> String
showsPrec :: Int -> Serial -> ShowS
$cshowsPrec :: Int -> Serial -> ShowS
Show)

-- | Generate a random 'Serial' number.
--
randomSerial :: MonadRandom m => m Serial
randomSerial :: forall (m :: * -> *). MonadRandom m => m Serial
randomSerial = Vector 7 Digit -> Serial
Serial forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (n :: Nat) (m :: * -> *) a.
(KnownNat n, Monad m) =>
m a -> m (Vector n a)
V.replicateM forall a (m :: * -> *). (MonadRandom m, Bounded a, Enum a) => m a
randomBoundedEnum