    module Codec.Binary.BubbleBabble(encode) where

    import Data.Array.Unboxed
    import Data.Bits
    import Data.Word

    import Codec.Utils

    vowel :: UArray Int Char
    vowel = listArray (0,5) "aeiouy"

    consonant :: UArray Int Char
    consonant = listArray (0,16) "bcdfghklmnprstvzx"

    -- | Encode binary data into the bubble babble human readable encoding.
    -- Bubble Babble is an encoding that represents binary data as psuedowords
    -- which are more pronouncable and memorable than standard hexadecimal encoding.
    --
    -- It is mainly used for representing cryptographic fingerprints.
    -- In addition, there is an amount of redundancy and error correction built into
    -- the representation so that transcription errors can be more readily identified.
    --
    -- see:  http://en.wikipedia.org/wiki/Bubble_Babble
    --

    encode :: [Octet] -> String
    encode cs = 'x' : bb 1 (map fromIntegral cs) where
        bb seed [] = vcvx  ((seed `mod` 6),16,(seed `div` 6))
        bb seed [x] = vcvx ((((x `shiftR` 6) .&. 3) + seed) `mod` 6, (x `shiftR` 2) .&. 15, ((x .&. 3) + (seed `div` 6)) `mod` 6)
        bb seed (x:y:xs) = vcvcc (a,b,c,d,e) $ bb ((seed * 5 + (x * 7 + y)) `mod` 36) xs where
            a = (((x `shiftR` 6) .&. 3) + seed) `mod` 6
            b = (x `shiftR` 2) .&. 15
            c = ((x .&. 3) + (seed `div` 6)) `mod` 6
            d = (y `shiftR` 4) .&. 15
            e = y .&. 15
        vcvx (a,b,c) = vowel!a : consonant!b : vowel!c : "x"
        vcvcc (a,b,c,d,e) xs =  vowel!a : consonant!b : vowel!c : consonant!d : '-' : consonant!e : xs