module Data.Niagra.Builder.Numbers
(
  decimal,
  hexadecimal,
  realFloat
)
where

import Data.Niagra.Builder

import Data.Char
import Data.Monoid
import Numeric

decimal :: Integral a => a -> Builder
decimal v
  | v < 0 = singleton '-' <> decimal (abs v)
  | v < 10 = singleton $ chr $ 48 + (fromIntegral v) -- prevent costly calc for single-digit numbers. This is a significant optimization, especially when building CSS (eg 2px).
  | otherwise = f mempty v
  where
    f acc 0 = acc
    f acc v = let (q,r) = quotRem v 10
                  c = chr $ 48 + (fromIntegral r)
              in f (singleton c <> acc) q

-- TODO: two's compliment signed hex
-- |Render a *signed* hexadecimal number to a Builder
hexadecimal :: Integral a => a -> Builder
hexadecimal v
  | v < 0 = error "UNIMPLEMENTED: negative hexadecimal two's compliment representations."
  | v == 0 = singleton '0'
  | otherwise = f mempty v
  where
    f acc 0 = acc
    f acc v = let (q,r) = quotRem v 16
                  c = hexChar r
              in f (singleton c <> acc) q
    hexChar v
      | v < 10 = chr $ 48 + (fromIntegral v)
      | otherwise = chr $ 65 + (fromIntegral v) - 10

realFloat :: (RealFloat a) => a -> Builder
realFloat v
  | v < 0 = singleton '-' <> realFloat (abs v)
  | otherwise = let (a,b) = floatToDigits 10 v
                    digits = map (chr . (+) 48) a
                    (leftOfDec,rightOfDec) = splitAt b digits
                in fromString leftOfDec <> singleton '.' <> fromString rightOfDec