-- | Point serialisation using https://tools.ietf.org/id/draft-jivsov-ecc-compact-05.html
-- It is unclear if 02 is smallest y or not so the following is used in the first 2 bytes
-- 01 - Point at infinity
-- 02 - Compressed repr i.e. x only but use smallest y on decode
-- 03 - Compressed repr i.e. x only but use largest y on decode
-- 04 -- Uncompressed repr i.e. x & y

module Pairing.Serialize.Jivsov where
--   ( Jivsov(..)
--   ) where
-- 
-- import Protolude hiding (putByteString)
-- import Pairing.Point
-- import Pairing.Serialize.Types
-- import Pairing.Fq
-- import Data.ByteString.Builder
-- import Data.ByteString as B hiding (length)
-- import qualified Data.ByteString as B
-- import Data.Binary.Get
-- import Data.Binary.Put (Put, putWord8, putWord16le, runPut, putByteString)
-- import Control.Error
-- import Pairing.ByteRepr
-- import Pairing.CyclicGroup
-- 
-- data Jivsov = Jivsov
-- 
-- instance MkCompressedForm Jivsov where
--   serializeCompressed _  = toCompressedForm
-- 
-- instance MkUncompressedForm Jivsov where
--   serializePointUncompressed _ = toUncompressedForm
--   serializeUncompressed _ = elementToUncompressedForm
-- 
-- instance FromSerialisedForm Jivsov where
--   unserializePoint _ = pointFromByteString
-- 
-- instance FromUncompressedForm Jivsov where
--   unserialize _ = elementReadUncompressed
-- 
-- putCompressionType :: Word8 -> Put
-- putCompressionType n = putWord8 0 >> putWord8 n
-- 
-- getCompressionType :: Get Word8
-- getCompressionType = getWord8 >> getWord8
-- 
-- -------------------------------------------------------------------------------
-- -- Element specific Serailisation
-- -------------------------------------------------------------------------------
-- 
-- elementToUncompressedForm :: (ByteRepr a) => a -> Maybe LByteString
-- elementToUncompressedForm a = do
--   repr <- mkRepr (ByteOrderLength MostSignificantFirst minReprLength) a
--   pure $ runPut $ do
--     putCompressionType 4
--     putByteString repr
-- 
-- elementReadUncompressed :: (Validate a, Show a, ByteRepr a) =>  a -> LByteString -> Either Text a
-- elementReadUncompressed ele = parseBS runc
--   where
--     runc = do
--       ctype <- getCompressionType
--       if ctype == 4 then do
--         let xlen = calcReprLength ele minReprLength
--         bs <- getByteString xlen
--         pure (fromRepr (ByteOrderLength MostSignificantFirst minReprLength) ele bs)
--       else
--         pure Nothing
-- 
-- -------------------------------------------------------------------------------
-- -- Point specific serialisation
-- -------------------------------------------------------------------------------
-- 
-- toUncompressedForm :: (ByteRepr a) => Point a -> Maybe LByteString
-- toUncompressedForm (Point x y) = do
--   rx <- mkRepr (ByteOrderLength MostSignificantFirst minReprLength) x
--   ry <- mkRepr (ByteOrderLength MostSignificantFirst minReprLength) y
--   pure $ runPut $ do
--     putCompressionType 4
--     putByteString rx
--     putByteString ry
-- toUncompressedForm Infinity = pure $ runPut (putCompressionType 1)
-- 
-- toCompressedForm :: (ByteRepr a, FromX a, Ord a) => Point a -> Maybe LByteString
-- toCompressedForm (Point x y) = do
--   ny <- yFromX x max
--   let yform = if ny == y then 3 else 2
--   rx <- mkRepr (ByteOrderLength MostSignificantFirst minReprLength) x
--   pure (runPut $ do
--            putCompressionType yform
--            putByteString rx)
-- toCompressedForm Infinity = Just (toLazyByteString (word8 0 <> word8 1))
-- 
-- pointFromByteString :: (Show a, Validate (Point a), ByteRepr a, FromX a, Ord a) => Point a -> LByteString -> Either Text (Point a)
-- pointFromByteString (Point a _) bs = parseBS fromByteStringGet bs
--   where
--     fromByteStringGet = do
--       ctype <- getCompressionType
--       processCompressed a ctype
-- pointFromByteString Infinity _ = Left "Cannot use infinity to extract from bytestring"
-- 
-- processCompressed :: forall a . (ByteRepr a, FromX a, Ord a) => a -> Word8 -> Get (Maybe (Point a))
-- processCompressed one ct
--   | ct == 4 = do
--       xbs <- getByteString blen
--       ybs <- getByteString blen
--       pure (buildPoint one (ByteOrderLength MostSignificantFirst minReprLength) xbs (ByteOrderLength MostSignificantFirst minReprLength) ybs)
--   | ct == 2 = fromCompressed False
--   | ct == 3 = fromCompressed True
--   | ct == 1 = pure (Just Infinity)
--   | otherwise = pure Nothing
--   where
--     blen = calcReprLength one minReprLength
--     fromCompressed largestY = runMaybeT $ do
--       xbs <- lift $ getByteString blen
--       x <- hoistMaybe $ fromRepr (ByteOrderLength MostSignificantFirst minReprLength) one xbs
--       y <- hoistMaybe $ yFromX x (\y1 y2 -> if largestY then max y1 y2 else min y1 y2)
--       pure (Point x y)