{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Crypto.JOSE.Error
  (
    Error(..)
  , AsError(..)
  
  , InvalidNumberOfParts(..), expectedParts, actualParts
  , CompactTextError(..)
  , CompactDecodeError(..)
  , _CompactInvalidNumberOfParts
  , _CompactInvalidText
  ) where
import Data.Semigroup ((<>))
import Numeric.Natural
import Control.Monad.Trans (MonadTrans(..))
import qualified Crypto.PubKey.RSA as RSA
import Crypto.Error (CryptoError)
import Crypto.Random (MonadRandom(..))
import Control.Lens (Getter, to)
import Control.Lens.TH (makeClassyPrisms, makePrisms)
import qualified Data.Text as T
import qualified Data.Text.Encoding.Error as T
data InvalidNumberOfParts =
  InvalidNumberOfParts Natural Natural 
  deriving (Eq)
instance Show InvalidNumberOfParts where
  show (InvalidNumberOfParts n m) =
    "Expected " <> show n <> " parts; got " <> show m
expectedParts, actualParts :: Getter InvalidNumberOfParts Natural
expectedParts = to $ \(InvalidNumberOfParts n _) -> n
actualParts   = to $ \(InvalidNumberOfParts _ n) -> n
data CompactTextError = CompactTextError
  Natural
  T.UnicodeException
  deriving (Eq)
instance Show CompactTextError where
  show (CompactTextError n s) =
    "Invalid text at part " <> show n <> ": " <> show s
data CompactDecodeError
  = CompactInvalidNumberOfParts InvalidNumberOfParts
  | CompactInvalidText CompactTextError
  deriving (Eq)
makePrisms ''CompactDecodeError
instance Show CompactDecodeError where
  show (CompactInvalidNumberOfParts e) = "Invalid number of parts: " <> show e
  show (CompactInvalidText e) = "Invalid text: " <> show e
data Error
  = AlgorithmNotImplemented   
  | AlgorithmMismatch String  
  | KeyMismatch T.Text        
  | KeySizeTooSmall           
  | OtherPrimesNotSupported   
  | RSAError RSA.Error        
  | CryptoError CryptoError   
  | CompactDecodeError CompactDecodeError
  
  | JSONDecodeError String    
  | NoUsableKeys              
  | JWSCritUnprotected
  | JWSNoValidSignatures
  
  | JWSInvalidSignature
  
  | JWSNoSignatures
  
  
  deriving (Eq, Show)
makeClassyPrisms ''Error
instance (
    MonadRandom m
  , MonadTrans t
  , Functor (t m)
  , Monad (t m)
  ) => MonadRandom (t m) where
    getRandomBytes = lift . getRandomBytes