-- | Determine if an entity's availability is 'Job.MayBecomeAvailable'. Fails if
-- the entity is 'Job.NeverAvailable' and the dependency is non-optional.
shouldWaitFor :: (TS m, MonadError JobError m) => Job.Dependency -> m Bool
shouldWaitFor (Job.Dependency name opt) =
    maybe (throwError $ JobMustBe name ExpectExtant) (chk . Job.anyAvailability) =<< ES.getEntity id name
  where
    chk Available              = pure False
    chk MayBecomeAvailable     = pure True
    -- Boxes can't become NeverAvailable, so it's fine to use a job-specific error
    chk NeverAvailable
        | opt                  = pure False
        | otherwise            = throwError $ JobMustBe name ExpectNonFailed
shouldWaitFor :: (TS m, MonadError JobError m) => Job.Dependency -> m Bool
shouldWaitFor (Job.Dependency name opt) =
    maybe (throwError $ JobMustBe name ExpectExtant) (chk . Job.anyAvailability) =<< ES.getEntity id name
  where
    chk Available              = pure False
    chk MayBecomeAvailable     = pure True
    -- Boxes can't become NeverAvailable, so it's fine to use a job-specific error
    chk NeverAvailable
        | opt                  = pure False
        | otherwise            = throwError $ JobMustBe name ExpectNonFailed
shouldWaitFor (Job.Dependency name opt) =
    maybe (throwError $ JobMustBe name ExpectExtant) (chk . Job.anyAvailability) =<< ES.getEntity id name
  where
    chk Available              = pure False
    chk MayBecomeAvailable     = pure True
    -- Boxes can't become NeverAvailable, so it's fine to use a job-specific error
    chk NeverAvailable
        | opt                  = pure False
        | otherwise            = throwError $ JobMustBe name ExpectNonFailed