module Reddit.Types.Error
  (RedditError(..)) where

import Control.Applicative
import Data.Aeson
import Data.Monoid
import Data.Text (Text)
import Data.Vector ((!?))
import Network.API.Builder.Receive
import Prelude
import qualified Data.Vector as V

data RedditError = RedditError Object
                 | FailError Text
                 | InvalidResponseError
                 | CaptchaError Text
                 | CredentialsError
                 | RateLimitError Integer Text
                 | NoSubredditSpecified
                 | NoURLSpecified
                 | NoName
                 | NoText Text
                 | AlreadySubmitted
                 | CommentDeleted
                 | LinkDeleted
                 | BadSubredditName
                 | TooManyRequests
                 | FlairTooLong
                 deriving (Int -> RedditError -> ShowS
[RedditError] -> ShowS
RedditError -> String
(Int -> RedditError -> ShowS)
-> (RedditError -> String)
-> ([RedditError] -> ShowS)
-> Show RedditError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [RedditError] -> ShowS
$cshowList :: [RedditError] -> ShowS
show :: RedditError -> String
$cshow :: RedditError -> String
showsPrec :: Int -> RedditError -> ShowS
$cshowsPrec :: Int -> RedditError -> ShowS
Show, RedditError -> RedditError -> Bool
(RedditError -> RedditError -> Bool)
-> (RedditError -> RedditError -> Bool) -> Eq RedditError
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RedditError -> RedditError -> Bool
$c/= :: RedditError -> RedditError -> Bool
== :: RedditError -> RedditError -> Bool
$c== :: RedditError -> RedditError -> Bool
Eq)

instance FromJSON RedditError where
  parseJSON :: Value -> Parser RedditError
parseJSON (Object Object
o) = do
    Array Array
errors <- Object
o Object -> Key -> Parser Object
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"json" Parser Object -> (Object -> Parser Value) -> Parser Value
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Object -> Key -> Parser Value
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"errors")
    case Array
errors Array -> Int -> Maybe Value
forall a. Vector a -> Int -> Maybe a
!? Int
0 of
      Just (Array Array
e) -> case Array -> [Value]
forall a. Vector a -> [a]
V.toList Array
e of
        String Text
"WRONG_PASSWORD" : [Value]
_ -> RedditError -> Parser RedditError
forall (m :: * -> *) a. Monad m => a -> m a
return RedditError
CredentialsError
        String Text
"USER_REQUIRED" : [Value]
_ -> RedditError -> Parser RedditError
forall (m :: * -> *) a. Monad m => a -> m a
return RedditError
CredentialsError
        String Text
"INCORRECT_USERNAME_PASSWORD" : [Value]
_ -> RedditError -> Parser RedditError
forall (m :: * -> *) a. Monad m => a -> m a
return RedditError
CredentialsError
        String Text
"RATELIMIT" : String Text
d : [Value]
_ ->
            Integer -> Text -> RedditError
RateLimitError (Integer -> Text -> RedditError)
-> Parser Integer -> Parser (Text -> RedditError)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((Object
o Object -> Key -> Parser Object
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"json") Parser Object -> (Object -> Parser Integer) -> Parser Integer
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Object -> Key -> Parser Integer
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"ratelimit")) Parser (Text -> RedditError) -> Parser Text -> Parser RedditError
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Parser Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
d
        String Text
"SUBREDDIT_REQUIRED" : [Value]
_ -> RedditError -> Parser RedditError
forall (m :: * -> *) a. Monad m => a -> m a
return RedditError
NoSubredditSpecified
        String Text
"ALREADY_SUB" : [Value]
_ -> RedditError -> Parser RedditError
forall (m :: * -> *) a. Monad m => a -> m a
return RedditError
AlreadySubmitted
        String Text
"NO_URL" : [Value]
_ -> RedditError -> Parser RedditError
forall (m :: * -> *) a. Monad m => a -> m a
return RedditError
NoURLSpecified
        String Text
"NO_NAME" : [Value]
_ -> RedditError -> Parser RedditError
forall (m :: * -> *) a. Monad m => a -> m a
return RedditError
NoName
        String Text
"NO_TEXT" : Value
_ : String Text
f : [Value]
_ -> RedditError -> Parser RedditError
forall (m :: * -> *) a. Monad m => a -> m a
return (RedditError -> Parser RedditError)
-> RedditError -> Parser RedditError
forall a b. (a -> b) -> a -> b
$ Text -> RedditError
NoText Text
f
        String Text
"COMMENT_DELETED" : [Value]
_ -> RedditError -> Parser RedditError
forall (m :: * -> *) a. Monad m => a -> m a
return RedditError
CommentDeleted
        String Text
"DELETED_LINK" : [Value]
_ -> RedditError -> Parser RedditError
forall (m :: * -> *) a. Monad m => a -> m a
return RedditError
LinkDeleted
        String Text
"BAD_SR_NAME" : [Value]
_ -> RedditError -> Parser RedditError
forall (m :: * -> *) a. Monad m => a -> m a
return RedditError
BadSubredditName
        String Text
"BAD_CAPTCHA" : [Value]
_ -> Text -> RedditError
CaptchaError (Text -> RedditError) -> Parser Text -> Parser RedditError
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Object
o Object -> Key -> Parser Object
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"json" Parser Object -> (Object -> Parser Text) -> Parser Text
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"captcha"))
        [Value]
_ -> RedditError -> Parser RedditError
forall (m :: * -> *) a. Monad m => a -> m a
return (RedditError -> Parser RedditError)
-> RedditError -> Parser RedditError
forall a b. (a -> b) -> a -> b
$ Object -> RedditError
RedditError Object
o
      Maybe Value
_ -> Parser RedditError
forall a. Monoid a => a
mempty
  parseJSON Value
_ = Parser RedditError
forall a. Monoid a => a
mempty

instance ErrorReceivable RedditError where
  receiveError :: Response ByteString -> Maybe RedditError
receiveError = Response ByteString -> Maybe RedditError
forall a. FromJSON a => Response ByteString -> Maybe a
useErrorFromJSON