module Restyler.App.Class
    ( HasWorkingDirectory(..)
    , HasSystem(..)
    , HasExit(..)
    , exitWithInfo
    , HasProcess(..)
    , HasDownloadFile(..)

    -- * GitHub
    , HasGitHub(..)
    , runGitHubFirst
    , runGitHub_

    -- ** Higher-level actions
    , getPullRequestLabelNames
    )
where

import Restyler.Prelude

import GitHub.Data (IssueLabel(..))
import GitHub.Data.Request
import GitHub.Endpoints.Issues.Labels (labelsOnIssueR)
import GitHub.Request
import Restyler.PullRequest
import qualified RIO.Vector as V

class HasWorkingDirectory env where
    workingDirectoryL :: Lens' env FilePath

class HasSystem env where
    getCurrentDirectory :: RIO env FilePath

    setCurrentDirectory :: FilePath -> RIO env ()

    doesFileExist :: FilePath -> RIO env Bool

    doesDirectoryExist :: FilePath -> RIO env Bool

    isFileExecutable :: FilePath -> RIO env Bool

    listDirectory :: FilePath -> RIO env [FilePath]

    readFile :: FilePath -> RIO env Text

    readFileBS :: FilePath -> RIO env ByteString

    writeFile :: FilePath -> Text -> RIO env ()

class HasExit env where
    exitSuccess :: RIO env a

exitWithInfo :: (HasLogFunc env, HasExit env) => Utf8Builder -> RIO env a
exitWithInfo :: Utf8Builder -> RIO env a
exitWithInfo msg :: Utf8Builder
msg = do
    Utf8Builder -> RIO env ()
forall (m :: * -> *) env.
(MonadIO m, MonadReader env m, HasLogFunc env, HasCallStack) =>
Utf8Builder -> m ()
logInfo Utf8Builder
msg
    RIO env a
forall env a. HasExit env => RIO env a
exitSuccess

class HasProcess env where
    callProcess :: String -> [String] -> RIO env ()

    callProcessExitCode :: String -> [String] -> RIO env ExitCode

    readProcess :: String -> [String] -> String -> RIO env String

class HasDownloadFile env where
    downloadFile :: Text -> FilePath -> RIO env ()

class HasGitHub env where
    runGitHub :: ParseResponse m a => GenRequest m k a -> RIO env a

-- | Fetch the first page using @'runGitHub'@, return the first item
runGitHubFirst
    :: (HasGitHub env, ParseResponse m (Vector a))
    => (FetchCount -> GenRequest m k (Vector a))
    -> RIO env (Maybe a)
runGitHubFirst :: (FetchCount -> GenRequest m k (Vector a)) -> RIO env (Maybe a)
runGitHubFirst f :: FetchCount -> GenRequest m k (Vector a)
f = (Vector a -> Int -> Maybe a
forall (v :: * -> *) a. Vector v a => v a -> Int -> Maybe a
V.!? 0) (Vector a -> Maybe a) -> RIO env (Vector a) -> RIO env (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenRequest m k (Vector a) -> RIO env (Vector a)
forall env (m :: MediaType *) a (k :: RW).
(HasGitHub env, ParseResponse m a) =>
GenRequest m k a -> RIO env a
runGitHub (FetchCount -> GenRequest m k (Vector a)
f 1)

-- | @'void' . 'runGitHub'@
runGitHub_
    :: (HasGitHub env, ParseResponse m a) => GenRequest m k a -> RIO env ()
runGitHub_ :: GenRequest m k a -> RIO env ()
runGitHub_ = RIO env a -> RIO env ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (RIO env a -> RIO env ())
-> (GenRequest m k a -> RIO env a)
-> GenRequest m k a
-> RIO env ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GenRequest m k a -> RIO env a
forall env (m :: MediaType *) a (k :: RW).
(HasGitHub env, ParseResponse m a) =>
GenRequest m k a -> RIO env a
runGitHub

getPullRequestLabelNames
    :: HasGitHub env => PullRequest -> RIO env (Vector (Name IssueLabel))
getPullRequestLabelNames :: PullRequest -> RIO env (Vector (Name IssueLabel))
getPullRequestLabelNames pullRequest :: PullRequest
pullRequest = do
    Vector IssueLabel
labels <- (SomeException -> RIO env (Vector IssueLabel))
-> RIO env (Vector IssueLabel) -> RIO env (Vector IssueLabel)
forall (m :: * -> *) a.
MonadUnliftIO m =>
(SomeException -> m a) -> m a -> m a
handleAny (RIO env (Vector IssueLabel)
-> SomeException -> RIO env (Vector IssueLabel)
forall a b. a -> b -> a
const (RIO env (Vector IssueLabel)
 -> SomeException -> RIO env (Vector IssueLabel))
-> RIO env (Vector IssueLabel)
-> SomeException
-> RIO env (Vector IssueLabel)
forall a b. (a -> b) -> a -> b
$ Vector IssueLabel -> RIO env (Vector IssueLabel)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Vector IssueLabel
forall a. Monoid a => a
mempty) (RIO env (Vector IssueLabel) -> RIO env (Vector IssueLabel))
-> RIO env (Vector IssueLabel) -> RIO env (Vector IssueLabel)
forall a b. (a -> b) -> a -> b
$ GenRequest 'MtJSON Any (Vector IssueLabel)
-> RIO env (Vector IssueLabel)
forall env (m :: MediaType *) a (k :: RW).
(HasGitHub env, ParseResponse m a) =>
GenRequest m k a -> RIO env a
runGitHub (GenRequest 'MtJSON Any (Vector IssueLabel)
 -> RIO env (Vector IssueLabel))
-> GenRequest 'MtJSON Any (Vector IssueLabel)
-> RIO env (Vector IssueLabel)
forall a b. (a -> b) -> a -> b
$ Name Owner
-> Name Repo
-> Id Issue
-> FetchCount
-> GenRequest 'MtJSON Any (Vector IssueLabel)
forall (k :: RW).
Name Owner
-> Name Repo
-> Id Issue
-> FetchCount
-> Request k (Vector IssueLabel)
labelsOnIssueR
        (HasCallStack => PullRequest -> Name Owner
PullRequest -> Name Owner
pullRequestOwnerName PullRequest
pullRequest)
        (HasCallStack => PullRequest -> Name Repo
PullRequest -> Name Repo
pullRequestRepoName PullRequest
pullRequest)
        (PullRequest -> Id Issue
pullRequestIssueId PullRequest
pullRequest)
        FetchCount
FetchAll
    Vector (Name IssueLabel) -> RIO env (Vector (Name IssueLabel))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Vector (Name IssueLabel) -> RIO env (Vector (Name IssueLabel)))
-> Vector (Name IssueLabel) -> RIO env (Vector (Name IssueLabel))
forall a b. (a -> b) -> a -> b
$ IssueLabel -> Name IssueLabel
labelName (IssueLabel -> Name IssueLabel)
-> Vector IssueLabel -> Vector (Name IssueLabel)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Vector IssueLabel
labels