{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeFamilies #-}

module Codec.QRCode.Data.QRImage
  ( QRImage(..)
  , toList
  , toMatrix
  ) where

import           Codec.QRCode.Base

import qualified Data.Vector.Unboxed          as UV

import           Codec.QRCode.Data.ErrorLevel

data QRImage
  = QRImage
    { QRImage -> Int
qrVersion    :: !Int
    , QRImage -> ErrorLevel
qrErrorLevel :: !ErrorLevel
    , QRImage -> Int
qrImageSize  :: !Int
    , QRImage -> Vector Bool
qrImageData  :: !(UV.Vector Bool)
    }

-- | Convert the QR code image into a list-type containing all
--   elements from top to bottom and left to right.
--   The values for black/white have to be specified.
toList
  :: (IsList l, Item l ~ a)
  => a -- ^ Value for black modules
  -> a -- ^ Value for white modules
  -> QRImage
  -> l
{-# INLINEABLE toList #-}
toList :: a -> a -> QRImage -> l
toList a
bl a
wh QRImage{Int
Vector Bool
ErrorLevel
qrImageData :: Vector Bool
qrImageSize :: Int
qrErrorLevel :: ErrorLevel
qrVersion :: Int
qrImageData :: QRImage -> Vector Bool
qrImageSize :: QRImage -> Int
qrErrorLevel :: QRImage -> ErrorLevel
qrVersion :: QRImage -> Int
..} =
  Int -> [Item l] -> l
forall l. IsList l => Int -> [Item l] -> l
fromListN
    (Int
qrImageSize Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
qrImageSize)
    ((Bool -> a) -> [Bool] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map
      (a -> a -> Bool -> a
forall a. a -> a -> Bool -> a
bool a
wh a
bl)
      (Vector Bool -> [Bool]
forall a. Unbox a => Vector a -> [a]
UV.toList Vector Bool
qrImageData)
    )

-- | Convert the QR code image into a list-type of list-type.
--   The values for black/white have to be specified.
toMatrix
  :: (IsList l, Item l ~ k, IsList k, Item k ~ a)
  => a -- ^ Value for black modules
  -> a -- ^ Value for white modules
  -> QRImage
  -> l
{-# INLINEABLE toMatrix #-}
toMatrix :: a -> a -> QRImage -> l
toMatrix a
bl a
wh QRImage{Int
Vector Bool
ErrorLevel
qrImageData :: Vector Bool
qrImageSize :: Int
qrErrorLevel :: ErrorLevel
qrVersion :: Int
qrImageData :: QRImage -> Vector Bool
qrImageSize :: QRImage -> Int
qrErrorLevel :: QRImage -> ErrorLevel
qrVersion :: QRImage -> Int
..} =
  Int -> [Item l] -> l
forall l. IsList l => Int -> [Item l] -> l
fromListN
    Int
qrImageSize
      ((Int -> k) -> [Int] -> [k]
forall a b. (a -> b) -> [a] -> [b]
map
        Int -> k
go
        [Int
0 .. Int
qrImageSize Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]
      )
  where
    go :: Int -> k
go Int
ofs =
      Int -> [Item k] -> k
forall l. IsList l => Int -> [Item l] -> l
fromListN
        Int
qrImageSize
        ((Bool -> a) -> [Bool] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map
          (a -> a -> Bool -> a
forall a. a -> a -> Bool -> a
bool a
wh a
bl)
          (Vector Bool -> [Bool]
forall a. Unbox a => Vector a -> [a]
UV.toList (Vector Bool -> [Bool]) -> Vector Bool -> [Bool]
forall a b. (a -> b) -> a -> b
$ Int -> Vector Bool -> Vector Bool
forall a. Unbox a => Int -> Vector a -> Vector a
UV.take Int
qrImageSize (Vector Bool -> Vector Bool) -> Vector Bool -> Vector Bool
forall a b. (a -> b) -> a -> b
$ Int -> Vector Bool -> Vector Bool
forall a. Unbox a => Int -> Vector a -> Vector a
UV.drop (Int
ofs Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
qrImageSize) Vector Bool
qrImageData)
        )