{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE TemplateHaskell #-}

-- |
-- Module: Captcha.Internal.Monad
-- Copyright: (c) 2022 Edward Yang
-- License: MIT
--
-- This module is for internal-use and does not follow pvp versioning policies.
module Captcha.Internal.Monad where

import Control.Lens.TH (makeClassy)
import Control.Monad.Cont (MonadIO (liftIO))
import Control.Monad.Reader (MonadReader, ReaderT (ReaderT))
import Network.Wreq.Session (Session, newSession)
import UnliftIO (MonadUnliftIO)

-- | Effect providing an environment required to solve captchas.
newtype Captcha a = Captcha
  { Captcha a -> CaptchaEnv -> IO a
runCaptcha :: CaptchaEnv -> IO a
  }
  deriving
    ( a -> Captcha b -> Captcha a
(a -> b) -> Captcha a -> Captcha b
(forall a b. (a -> b) -> Captcha a -> Captcha b)
-> (forall a b. a -> Captcha b -> Captcha a) -> Functor Captcha
forall a b. a -> Captcha b -> Captcha a
forall a b. (a -> b) -> Captcha a -> Captcha b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> Captcha b -> Captcha a
$c<$ :: forall a b. a -> Captcha b -> Captcha a
fmap :: (a -> b) -> Captcha a -> Captcha b
$cfmap :: forall a b. (a -> b) -> Captcha a -> Captcha b
Functor,
      Functor Captcha
a -> Captcha a
Functor Captcha
-> (forall a. a -> Captcha a)
-> (forall a b. Captcha (a -> b) -> Captcha a -> Captcha b)
-> (forall a b c.
    (a -> b -> c) -> Captcha a -> Captcha b -> Captcha c)
-> (forall a b. Captcha a -> Captcha b -> Captcha b)
-> (forall a b. Captcha a -> Captcha b -> Captcha a)
-> Applicative Captcha
Captcha a -> Captcha b -> Captcha b
Captcha a -> Captcha b -> Captcha a
Captcha (a -> b) -> Captcha a -> Captcha b
(a -> b -> c) -> Captcha a -> Captcha b -> Captcha c
forall a. a -> Captcha a
forall a b. Captcha a -> Captcha b -> Captcha a
forall a b. Captcha a -> Captcha b -> Captcha b
forall a b. Captcha (a -> b) -> Captcha a -> Captcha b
forall a b c. (a -> b -> c) -> Captcha a -> Captcha b -> Captcha c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
<* :: Captcha a -> Captcha b -> Captcha a
$c<* :: forall a b. Captcha a -> Captcha b -> Captcha a
*> :: Captcha a -> Captcha b -> Captcha b
$c*> :: forall a b. Captcha a -> Captcha b -> Captcha b
liftA2 :: (a -> b -> c) -> Captcha a -> Captcha b -> Captcha c
$cliftA2 :: forall a b c. (a -> b -> c) -> Captcha a -> Captcha b -> Captcha c
<*> :: Captcha (a -> b) -> Captcha a -> Captcha b
$c<*> :: forall a b. Captcha (a -> b) -> Captcha a -> Captcha b
pure :: a -> Captcha a
$cpure :: forall a. a -> Captcha a
$cp1Applicative :: Functor Captcha
Applicative,
      Applicative Captcha
a -> Captcha a
Applicative Captcha
-> (forall a b. Captcha a -> (a -> Captcha b) -> Captcha b)
-> (forall a b. Captcha a -> Captcha b -> Captcha b)
-> (forall a. a -> Captcha a)
-> Monad Captcha
Captcha a -> (a -> Captcha b) -> Captcha b
Captcha a -> Captcha b -> Captcha b
forall a. a -> Captcha a
forall a b. Captcha a -> Captcha b -> Captcha b
forall a b. Captcha a -> (a -> Captcha b) -> Captcha b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: a -> Captcha a
$creturn :: forall a. a -> Captcha a
>> :: Captcha a -> Captcha b -> Captcha b
$c>> :: forall a b. Captcha a -> Captcha b -> Captcha b
>>= :: Captcha a -> (a -> Captcha b) -> Captcha b
$c>>= :: forall a b. Captcha a -> (a -> Captcha b) -> Captcha b
$cp1Monad :: Applicative Captcha
Monad,
      Monad Captcha
Monad Captcha -> (forall a. IO a -> Captcha a) -> MonadIO Captcha
IO a -> Captcha a
forall a. IO a -> Captcha a
forall (m :: * -> *).
Monad m -> (forall a. IO a -> m a) -> MonadIO m
liftIO :: IO a -> Captcha a
$cliftIO :: forall a. IO a -> Captcha a
$cp1MonadIO :: Monad Captcha
MonadIO,
      MonadReader CaptchaEnv,
      MonadIO Captcha
MonadIO Captcha
-> (forall b. ((forall a. Captcha a -> IO a) -> IO b) -> Captcha b)
-> MonadUnliftIO Captcha
((forall a. Captcha a -> IO a) -> IO b) -> Captcha b
forall b. ((forall a. Captcha a -> IO a) -> IO b) -> Captcha b
forall (m :: * -> *).
MonadIO m
-> (forall b. ((forall a. m a -> IO a) -> IO b) -> m b)
-> MonadUnliftIO m
withRunInIO :: ((forall a. Captcha a -> IO a) -> IO b) -> Captcha b
$cwithRunInIO :: forall b. ((forall a. Captcha a -> IO a) -> IO b) -> Captcha b
$cp1MonadUnliftIO :: MonadIO Captcha
MonadUnliftIO
    )
    via ReaderT CaptchaEnv IO

-- | Provides an HTTP 'Session' to be reused for each request.
newtype CaptchaEnv = CaptchaEnv
  { CaptchaEnv -> Session
_session :: Session
  }

makeClassy ''CaptchaEnv

-- | Create the environment required to solve captchas.
mkCaptchaEnv :: MonadIO m => m CaptchaEnv
mkCaptchaEnv :: m CaptchaEnv
mkCaptchaEnv = Session -> CaptchaEnv
CaptchaEnv (Session -> CaptchaEnv) -> m Session -> m CaptchaEnv
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO Session -> m Session
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO Session
newSession