{-# LANGUAGE NoImplicitPrelude #-}

module Codec.QRCode.Data.QRSegment.Internal
  ( QRSegment(..)
  , constStream
  , encodeBits
  , lengthSegment
  ) where

import           Codec.QRCode.Base

import qualified Codec.QRCode.Data.ByteStreamBuilder as BSB
import           Codec.QRCode.Data.Result
import           Codec.QRCode.Data.Version

-- | An segment of encoded data
newtype QRSegment
  = QRSegment
    { unQRSegment :: VersionRange -> Result BSB.ByteStreamBuilder
    }

instance Semigroup QRSegment where
  {-# INLINE (<>) #-}
  QRSegment a <> QRSegment b = QRSegment $ \v -> (<>) <$> a v <*> b v

constStream :: BSB.ByteStreamBuilder -> QRSegment
{-# INLINABLE constStream #-}
constStream = QRSegment . const . pure

encodeBits :: Int -> Int -> QRSegment
{-# INLINABLE encodeBits #-}
encodeBits len = constStream . BSB.encodeBits len

lengthSegment :: (Int, Int, Int) -> Int -> QRSegment
{-# INLINABLE lengthSegment #-}
lengthSegment (n1_9, n10_26, n27_40) l = QRSegment $ \vr ->
  let
    n =
      case vr of
        Version1to9   -> n1_9
        Version10to26 -> n10_26
        Version27to40 -> n27_40
  in
    if l >= (1 `shiftL` n)
      then empty
      else pure $ BSB.encodeBits n l