module Test.QuickCheck.Classes.HttpApiData
  ( httpApiDataLaws
  ) where

import ClassyPrelude
import Test.QuickCheck
import Test.QuickCheck.Classes
import Web.HttpApiData
import Data.Proxy
import Network.HTTP.Types.URI (encodePathSegmentsRelative)

import qualified Data.ByteString.Lazy.Char8 as LCBS
import qualified Data.ByteString.Builder as BS

httpApiDataLaws :: forall a. (Arbitrary a, ToHttpApiData a, FromHttpApiData a, Eq a, Show a) => Proxy a -> Laws
httpApiDataLaws _ = Laws "ToHttpApiData/FromHttpApiData"
  [ ("Partial Isomorphism (UrlPiece)", property $ \(a :: a) -> parseUrlPiece (toUrlPiece a) == Right a)
  , ("Encoding Equals Value (UrlPiece)", property $ \(a :: a) -> BS.toLazyByteString (toEncodedUrlPiece a) == BS.toLazyByteString (encodePathSegmentsRelative . pure $ toUrlPiece a))
  , ("Produces only valid characters (UrlPiece)", property $ \(a :: a) -> LCBS.all validUrlChar (BS.toLazyByteString $ toEncodedUrlPiece a) )
  , ("Partial Isomorphism (Header)", property $ \(a :: a) -> parseHeader (toHeader a) == Right a)
  , ("Partial Isomorphism (QueryParam)", property $ \(a :: a) -> parseQueryParam (toQueryParam a) == Right a)
  ]
  where
    validUrlChar :: Char -> Bool
    validUrlChar = flip elem $ ['a'..'z'] ++ ['A'..'Z'] ++ ['0'..'9'] ++ "-_.~:@&=+$," ++ "%"
