module Stackctl.RemovedStack
  ( inferRemovedStacks
  ) where

import Stackctl.Prelude

import Control.Error.Util (hoistMaybe)
import Control.Monad.Trans.Maybe (MaybeT (..), runMaybeT)
import Stackctl.AWS.CloudFormation
import Stackctl.AWS.Core
import Stackctl.AWS.Scope
import Stackctl.FilterOption
import UnliftIO.Directory (doesFileExist)

inferRemovedStacks
  :: ( MonadUnliftIO m
     , MonadResource m
     , MonadReader env m
     , HasAwsEnv env
     , HasAwsScope env
     , HasFilterOption env
     )
  => m [Stack]
inferRemovedStacks :: forall (m :: * -> *) env.
(MonadUnliftIO m, MonadResource m, MonadReader env m,
 HasAwsEnv env, HasAwsScope env, HasFilterOption env) =>
m [Stack]
inferRemovedStacks = do
  AwsScope
scope <- forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall env. HasAwsScope env => Lens' env AwsScope
awsScopeL
  [FilePath]
paths <- forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a b. (a -> b) -> a -> b
$ forall env. HasFilterOption env => Lens' env FilterOption
filterOptionL forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s a. (s -> a) -> SimpleGetter s a
to FilterOption -> [FilePath]
filterOptionToPaths
  forall a. [Maybe a] -> [a]
catMaybes forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (forall (m :: * -> *) env.
(MonadUnliftIO m, MonadResource m, MonadReader env m,
 HasAwsEnv env) =>
AwsScope -> FilePath -> m (Maybe Stack)
findRemovedStack AwsScope
scope) [FilePath]
paths

findRemovedStack
  :: (MonadUnliftIO m, MonadResource m, MonadReader env m, HasAwsEnv env)
  => AwsScope
  -> FilePath
  -> m (Maybe Stack)
findRemovedStack :: forall (m :: * -> *) env.
(MonadUnliftIO m, MonadResource m, MonadReader env m,
 HasAwsEnv env) =>
AwsScope -> FilePath -> m (Maybe Stack)
findRemovedStack AwsScope
scope FilePath
path = forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT forall a b. (a -> b) -> a -> b
$ do
  -- The filter is a full path to a specification in the current
  -- account/region...
  StackName
stackName <- forall (m :: * -> *) b. Monad m => Maybe b -> MaybeT m b
hoistMaybe forall a b. (a -> b) -> a -> b
$ AwsScope -> FilePath -> Maybe StackName
awsScopeSpecStackName AwsScope
scope FilePath
path

  -- that no longer exists...
  forall (f :: * -> *). Alternative f => Bool -> f ()
guard forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Bool
not forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *). MonadIO m => FilePath -> m Bool
doesFileExist FilePath
path

  -- but the Stack it would point to does
  forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) env.
(MonadUnliftIO m, MonadResource m, MonadReader env m,
 HasAwsEnv env) =>
StackName -> m (Maybe Stack)
awsCloudFormationDescribeStackMaybe StackName
stackName