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

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 :: forall l a. (IsList l, Item l ~ a) => 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
..} =
  forall l. IsList l => Int -> [Item l] -> l
fromListN
    (Int
qrImageSize forall a. Num a => a -> a -> a
* Int
qrImageSize)
    (forall a b. (a -> b) -> [a] -> [b]
map
      (forall a. a -> a -> Bool -> a
bool a
wh a
bl)
      (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 :: forall l k a.
(IsList l, Item l ~ k, IsList k, Item k ~ a) =>
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
..} =
  forall l. IsList l => Int -> [Item l] -> l
fromListN
    Int
qrImageSize
      (forall a b. (a -> b) -> [a] -> [b]
map
        Int -> k
go
        [Int
0 .. Int
qrImageSize forall a. Num a => a -> a -> a
- Int
1]
      )
  where
    go :: Int -> k
go Int
ofs =
      forall l. IsList l => Int -> [Item l] -> l
fromListN
        Int
qrImageSize
        (forall a b. (a -> b) -> [a] -> [b]
map
          (forall a. a -> a -> Bool -> a
bool a
wh a
bl)
          (forall a. Unbox a => Vector a -> [a]
UV.toList forall a b. (a -> b) -> a -> b
$ forall a. Unbox a => Int -> Vector a -> Vector a
UV.take Int
qrImageSize forall a b. (a -> b) -> a -> b
$ forall a. Unbox a => Int -> Vector a -> Vector a
UV.drop (Int
ofs forall a. Num a => a -> a -> a
* Int
qrImageSize) Vector Bool
qrImageData)
        )