{-# LANGUAGE GADTs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE AllowAmbiguousTypes #-}

-- |
-- Defines @UncheckedEnc@ representing not verified encoding and basic combinators for using it. 
--
-- This module is re-exported in "Data.TypedEncoding" and it is best not to import it directly.

module Data.TypedEncoding.Common.Types.UncheckedEnc where

import           Data.Proxy
import           Data.TypedEncoding.Common.Class.Common
import           Data.TypedEncoding.Common.Types.Common

-- $setup
-- >>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds -XAllowAmbiguousTypes
-- >>> import qualified Data.Text as T


-- * UncheckedEnc for validation, similar to CheckedEnc but not verified

-- | Represents some encoded string where encoding was not validated.
--
-- Encoding is not tracked at the type level.
--
-- Similar to 'Data.TypedEncoding.Common.Types.CheckedEnc' but unlike
-- @CheckedEnc@ it can contain payloads that have invalid encoding.
-- 
-- See 'Data.TypedEncoding.Combinators.Validate.check'
-- 
-- @since 0.2.0.0  
data UncheckedEnc c str = MkUncheckedEnc [EncAnn] c str deriving (Int -> UncheckedEnc c str -> ShowS
[UncheckedEnc c str] -> ShowS
UncheckedEnc c str -> String
(Int -> UncheckedEnc c str -> ShowS)
-> (UncheckedEnc c str -> String)
-> ([UncheckedEnc c str] -> ShowS)
-> Show (UncheckedEnc c str)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall c str.
(Show c, Show str) =>
Int -> UncheckedEnc c str -> ShowS
forall c str. (Show c, Show str) => [UncheckedEnc c str] -> ShowS
forall c str. (Show c, Show str) => UncheckedEnc c str -> String
showList :: [UncheckedEnc c str] -> ShowS
$cshowList :: forall c str. (Show c, Show str) => [UncheckedEnc c str] -> ShowS
show :: UncheckedEnc c str -> String
$cshow :: forall c str. (Show c, Show str) => UncheckedEnc c str -> String
showsPrec :: Int -> UncheckedEnc c str -> ShowS
$cshowsPrec :: forall c str.
(Show c, Show str) =>
Int -> UncheckedEnc c str -> ShowS
Show, UncheckedEnc c str -> UncheckedEnc c str -> Bool
(UncheckedEnc c str -> UncheckedEnc c str -> Bool)
-> (UncheckedEnc c str -> UncheckedEnc c str -> Bool)
-> Eq (UncheckedEnc c str)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall c str.
(Eq c, Eq str) =>
UncheckedEnc c str -> UncheckedEnc c str -> Bool
/= :: UncheckedEnc c str -> UncheckedEnc c str -> Bool
$c/= :: forall c str.
(Eq c, Eq str) =>
UncheckedEnc c str -> UncheckedEnc c str -> Bool
== :: UncheckedEnc c str -> UncheckedEnc c str -> Bool
$c== :: forall c str.
(Eq c, Eq str) =>
UncheckedEnc c str -> UncheckedEnc c str -> Bool
Eq)

-- |
-- @since 0.2.0.0 
toUncheckedEnc :: [EncAnn] -> c -> str -> UncheckedEnc c str
toUncheckedEnc :: [String] -> c -> str -> UncheckedEnc c str
toUncheckedEnc = [String] -> c -> str -> UncheckedEnc c str
forall c str. [String] -> c -> str -> UncheckedEnc c str
MkUncheckedEnc

-- |
-- @since 0.2.0.0 
getUncheckedEncAnn :: UncheckedEnc c str -> [EncAnn]
getUncheckedEncAnn :: UncheckedEnc c str -> [String]
getUncheckedEncAnn (MkUncheckedEnc [String]
ann c
_ str
_) = [String]
ann


getUncheckedPayload :: forall c str . UncheckedEnc c str -> str
getUncheckedPayload :: UncheckedEnc c str -> str
getUncheckedPayload (MkUncheckedEnc [String]
_ c
_ str
str) = str
str

-- |
-- @since 0.2.0.0 
verifyAnn :: forall xs c str . SymbolList xs => UncheckedEnc c str -> Either String (UncheckedEnc c str)
verifyAnn :: UncheckedEnc c str -> Either String (UncheckedEnc c str)
verifyAnn x :: UncheckedEnc c str
x@(MkUncheckedEnc [String]
xs c
_ str
_) = 
    let p :: Proxy @[Symbol] xs
p = Proxy @[Symbol] xs
forall k (t :: k). Proxy @k t
Proxy :: Proxy xs
    in if SymbolList xs => [String]
forall (xs :: [Symbol]). SymbolList xs => [String]
symbolVals @xs [String] -> [String] -> Bool
forall a. Eq a => a -> a -> Bool
== [String]
xs
       then UncheckedEnc c str -> Either String (UncheckedEnc c str)
forall a b. b -> Either a b
Right UncheckedEnc c str
x
       else String -> Either String (UncheckedEnc c str)
forall a b. a -> Either a b
Left (String -> Either String (UncheckedEnc c str))
-> String -> Either String (UncheckedEnc c str)
forall a b. (a -> b) -> a -> b
$ String
"UncheckedEnc has not matching annotation " String -> ShowS
forall a. [a] -> [a] -> [a]
++ [String] -> String
forall x. Displ x => x -> String
displ [String]
xs

-- |
-- >>> displ $ MkUncheckedEnc ["TEST"] () ("hello" :: T.Text)
-- "MkUncheckedEnc [TEST] () (Text hello)"
instance (Show c, Displ str) => Displ (UncheckedEnc c str) where
    displ :: UncheckedEnc c str -> String
displ (MkUncheckedEnc [String]
xs c
c str
s) = 
        String
"MkUncheckedEnc " String -> ShowS
forall a. [a] -> [a] -> [a]
++ [String] -> String
forall x. Displ x => x -> String
displ [String]
xs String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ c -> String
forall a. Show a => a -> String
show c
c String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ str -> String
forall x. Displ x => x -> String
displ str
s