{-# LANGUAGE LambdaCase #-}

module Restyler.RestylerResult
    ( RestylerResult(..)
    , noPathsRestylerResult
    , getRestylerResult
    , restylerCommittedChanges
    )
where

import Restyler.Prelude

import Restyler.Git
import Restyler.Restyler

data RestyleOutcome
    = NoPaths
    | NoChanges
    | ChangesCommitted [FilePath] Text

instance Display RestyleOutcome where
    display :: RestyleOutcome -> Utf8Builder
display = \case
        NoPaths -> "no paths to restyle"
        NoChanges -> "nothing restyled"
        ChangesCommitted paths :: [FilePath]
paths sha :: Text
sha ->
            "updated "
                Utf8Builder -> Utf8Builder -> Utf8Builder
forall a. Semigroup a => a -> a -> a
<> Int -> Utf8Builder
forall a. Show a => a -> Utf8Builder
displayShow ([FilePath] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [FilePath]
paths)
                Utf8Builder -> Utf8Builder -> Utf8Builder
forall a. Semigroup a => a -> a -> a
<> " file(s),"
                Utf8Builder -> Utf8Builder -> Utf8Builder
forall a. Semigroup a => a -> a -> a
<> " commited in "
                Utf8Builder -> Utf8Builder -> Utf8Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Utf8Builder
forall a. Display a => a -> Utf8Builder
display Text
sha

data RestylerResult = RestylerResult
    { RestylerResult -> Restyler
rrRestyler :: Restyler
    , RestylerResult -> RestyleOutcome
rrOutcome :: RestyleOutcome
    }

instance Display RestylerResult where
    display :: RestylerResult -> Utf8Builder
display RestylerResult {..} =
        FilePath -> Utf8Builder
forall a. IsString a => FilePath -> a
fromString (Restyler -> FilePath
rName Restyler
rrRestyler) Utf8Builder -> Utf8Builder -> Utf8Builder
forall a. Semigroup a => a -> a -> a
<> ": " Utf8Builder -> Utf8Builder -> Utf8Builder
forall a. Semigroup a => a -> a -> a
<> RestyleOutcome -> Utf8Builder
forall a. Display a => a -> Utf8Builder
display RestyleOutcome
rrOutcome

-- | A @'RestylerResult'@ indicating there were no paths to restyle
noPathsRestylerResult :: Restyler -> RestylerResult
noPathsRestylerResult :: Restyler -> RestylerResult
noPathsRestylerResult r :: Restyler
r = Restyler -> RestyleOutcome -> RestylerResult
RestylerResult Restyler
r RestyleOutcome
NoPaths

-- | Build a @'RestylerResult'@ based on what @git@ says
--
-- N.B. This will create commits if appropriate.
--
getRestylerResult :: HasGit env => Restyler -> RIO env RestylerResult
getRestylerResult :: Restyler -> RIO env RestylerResult
getRestylerResult r :: Restyler
r = Restyler -> RestyleOutcome -> RestylerResult
RestylerResult Restyler
r (RestyleOutcome -> RestylerResult)
-> RIO env RestyleOutcome -> RIO env RestylerResult
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Restyler -> RIO env RestyleOutcome
forall env. HasGit env => Restyler -> RIO env RestyleOutcome
getRestyleOutcome Restyler
r

-- | Does this @'RestylerResult'@ indicate changes were comitted?
restylerCommittedChanges :: RestylerResult -> Bool
restylerCommittedChanges :: RestylerResult -> Bool
restylerCommittedChanges = RestyleOutcome -> Bool
committedChanges (RestyleOutcome -> Bool)
-> (RestylerResult -> RestyleOutcome) -> RestylerResult -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RestylerResult -> RestyleOutcome
rrOutcome
  where
    committedChanges :: RestyleOutcome -> Bool
committedChanges (ChangesCommitted _ _) = Bool
True
    committedChanges _ = Bool
False

getRestyleOutcome :: HasGit env => Restyler -> RIO env RestyleOutcome
getRestyleOutcome :: Restyler -> RIO env RestyleOutcome
getRestyleOutcome restyler :: Restyler
restyler = do
    [FilePath]
changedPaths <- Maybe FilePath -> RIO env [FilePath]
forall env. HasGit env => Maybe FilePath -> RIO env [FilePath]
gitDiffNameOnly Maybe FilePath
forall a. Maybe a
Nothing

    if [FilePath] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [FilePath]
changedPaths
        then RestyleOutcome -> RIO env RestyleOutcome
forall (f :: * -> *) a. Applicative f => a -> f a
pure RestyleOutcome
NoChanges
        else [FilePath] -> Text -> RestyleOutcome
ChangesCommitted [FilePath]
changedPaths (Text -> RestyleOutcome)
-> (FilePath -> Text) -> FilePath -> RestyleOutcome
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Text
pack (FilePath -> RestyleOutcome)
-> RIO env FilePath -> RIO env RestyleOutcome
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> RIO env FilePath
forall env. HasGit env => FilePath -> RIO env FilePath
gitCommitAll FilePath
commitMessage
    where commitMessage :: FilePath
commitMessage = "Restyled by " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> Restyler -> FilePath
rName Restyler
restyler