{-# LANGUAGE BinaryLiterals #-}
{-# LANGUAGE NoImplicitPrelude #-}

module Codec.QRCode.Mode.Numeric
  ( numeric
  , numericB
  ) where

import           Codec.QRCode.Base

import qualified Codec.QRCode.Data.ByteStreamBuilder  as BSB
import           Codec.QRCode.Data.QRSegment.Internal
import           Codec.QRCode.Data.Result
import           Codec.QRCode.Data.ToInput

-- | Generate a segment representing the specified string of decimal digits encoded in numeric mode.
numeric :: ToNumeric a => a -> Result QRSegment
numeric :: forall a. ToNumeric a => a -> Result QRSegment
numeric a
s =
  case forall a. ToNumeric a => a -> [Int]
toNumeric a
s of
    [] -> forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteStreamBuilder -> QRSegment
constStream forall a. Monoid a => a
mempty)
    [Int]
s' -> ((Int -> Int -> QRSegment
encodeBits Int
4 Int
0b0001 forall a. Semigroup a => a -> a -> a
<> (Int, Int, Int) -> Int -> QRSegment
lengthSegment (Int
10, Int
12, Int
14) (forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
s')) forall a. Semigroup a => a -> a -> a
<>) forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteStreamBuilder -> QRSegment
constStream forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. ToNumeric a => a -> Result ByteStreamBuilder
numericB [Int]
s'

numericB :: ToNumeric a => a -> Result BSB.ByteStreamBuilder
numericB :: forall a. ToNumeric a => a -> Result ByteStreamBuilder
numericB a
s
  | forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (\Int
c -> Int
c forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
c forall a. Ord a => a -> a -> Bool
<= Int
9) [Int]
s' = forall (f :: * -> *) a. Applicative f => a -> f a
pure ([Int] -> ByteStreamBuilder
go [Int]
s')
  | Bool
otherwise = forall (f :: * -> *) a. Alternative f => f a
empty
  where
    s' :: [Int]
    s' :: [Int]
s' = forall a. ToNumeric a => a -> [Int]
toNumeric a
s
    go :: [Int] -> BSB.ByteStreamBuilder
    go :: [Int] -> ByteStreamBuilder
go (Int
a:Int
b:Int
c:[Int]
cs) = Int -> Int -> ByteStreamBuilder
BSB.encodeBits Int
10 (Int
a forall a. Num a => a -> a -> a
* Int
100 forall a. Num a => a -> a -> a
+ Int
b forall a. Num a => a -> a -> a
* Int
10 forall a. Num a => a -> a -> a
+ Int
c) forall a. Semigroup a => a -> a -> a
<> [Int] -> ByteStreamBuilder
go [Int]
cs
    go [Int
a,Int
b]      = Int -> Int -> ByteStreamBuilder
BSB.encodeBits Int
7 (Int
a forall a. Num a => a -> a -> a
* Int
10 forall a. Num a => a -> a -> a
+ Int
b)
    go [Int
a]        = Int -> Int -> ByteStreamBuilder
BSB.encodeBits Int
4 Int
a
    go []         = forall a. Monoid a => a
mempty