module Graphics.GChart.DataEncoding where

import Graphics.GChart.Types

import Data.List(intercalate)
import Data.Char (chr, ord)
import Numeric (showHex)


-- Data Encodings

encodeSimple :: [[Int]] -> String
encodeSimple datas = "s:" ++ intercalate "," (map (map enc) datas) where
    enc :: Int -> Char
    enc i | i >= 0  && i <= 25 = chr (ord 'A' + i)
          | i >= 26 && i <= 51 = chr (ord 'a' + (i - 26))
          | i >= 52 && i <= 61 = chr (ord '0' + (i - 52))
          | otherwise          = '_'

encSimpleReverse :: Char -> Int
encSimpleReverse c | ord c >= ord 'A' && ord c <= ord 'Z' = ord c - ord 'A'
                   | ord c >= ord 'a' && ord c <= ord 'z' = 26 + (ord c - ord 'a')
                   | ord c >= ord '0' && ord c <= ord '9' = 52 + (ord c - ord '0')
                   | otherwise = -1

-- FIXME This assumes all data is in range.
encodeText datas = "t:" ++ intercalate "|" (map encData datas) where
    encData = intercalate "," . map showDecimal

showDecimal :: Float -> String
showDecimal i | makeFloat (truncate i) - i == 0  = show $ truncate i
              | otherwise                            = show (fromIntegral (round (i * 10.0)) / 10.0)

makeFloat i = fromIntegral i :: Float

encodeExtended datas = "e:" ++ intercalate "," (map (concatMap encDatum) datas) where
    encDatum i | i >= 0 && i < 4096 = let (a, b) = i `quotRem` 64 in
                                      [encChar a, encChar b]
               | otherwise          = "__"
    encChar i | i >= 0  && i <= 25 = chr (ord 'A' + i)
              | i >= 26 && i <= 51 = chr (ord 'a' + (i - 26))
              | i >= 52 && i <= 61 = chr (ord '0' + (i - 52))
              | i == 62            = '-'
              | i == 63            = '.'


-- | URL-encode a string.
urlEnc str = concatMap enc str where
  enc c | c >= 'A' && c <= 'Z' = [c]
        | c >= 'a' && c <= 'z' = [c]
        | c >= '0' && c <= '9' = [c]
        | c `elem` safe        = [c]
        | c == ' '             = "+"
        | otherwise  = '%': showHex (ord c) ""
  -- Argh, different resources differ on which characters need escaping.
  -- This is likely wrong.
  safe = "$-_.!*'(),|:"