module Vimeta.UI.Term.Movie
( movieSearch,
)
where
import Byline.Menu
import Network.API.TheMovieDB
import Vimeta.Core
import Vimeta.UI.Common.Util
import Vimeta.UI.Term.Common
newtype MovieItem = MovieItem Movie
instance ToStylizedText MovieItem where
toStylizedText :: MovieItem -> Stylized Text
toStylizedText (MovieItem Movie
m) =
[Stylized Text] -> Stylized Text
forall a. Monoid a => [a] -> a
mconcat
[ Text -> Stylized Text
text (Movie -> Text
movieTitle Movie
m),
Text -> Stylized Text
text (Text -> Text
parens (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ Maybe Day -> Text
dayAsYear (Maybe Day -> Text) -> Maybe Day -> Text
forall a b. (a -> b) -> a -> b
$ Movie -> Maybe Day
movieReleaseDate Movie
m)
]
movieSearch :: MonadIO m => Text -> Vimeta m Movie
movieSearch :: Text -> Vimeta m Movie
movieSearch Text
initial = do
Text
name <- Stylized Text
-> Maybe Text
-> (Text -> Vimeta m (Either (Stylized Text) Text))
-> Vimeta m Text
forall (m :: * -> *) a e b.
(MonadByline m, ToStylizedText a, ToStylizedText e) =>
a -> Maybe Text -> (Text -> m (Either e b)) -> m b
askUntil Stylized Text
searchPrompt (Text -> Maybe Text
forall a. a -> Maybe a
Just Text
initial) (Either (Stylized Text) Text
-> Vimeta m (Either (Stylized Text) Text)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either (Stylized Text) Text
-> Vimeta m (Either (Stylized Text) Text))
-> (Text -> Either (Stylized Text) Text)
-> Text
-> Vimeta m (Either (Stylized Text) Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Stylized Text -> Text -> Either (Stylized Text) Text
notBlank Stylized Text
searchErr)
NonEmpty MovieItem
movies <-
TheMovieDB [Movie] -> Vimeta m [Movie]
forall (m :: * -> *) a. MonadIO m => TheMovieDB a -> Vimeta m a
tmdb (Text -> TheMovieDB [Movie]
searchMovies Text
name)
Vimeta m [Movie]
-> ([Movie] -> Vimeta m (NonEmpty MovieItem))
-> Vimeta m (NonEmpty MovieItem)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ( [Movie] -> Maybe (NonEmpty Movie)
forall a. [a] -> Maybe (NonEmpty a)
nonEmpty ([Movie] -> Maybe (NonEmpty Movie))
-> (Maybe (NonEmpty Movie) -> Vimeta m (NonEmpty MovieItem))
-> [Movie]
-> Vimeta m (NonEmpty MovieItem)
forall k (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> \case
Maybe (NonEmpty Movie)
Nothing -> String -> Vimeta m (NonEmpty MovieItem)
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (String
"no matches for: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Text -> String
forall a. ToString a => a -> String
toString Text
name)
Just NonEmpty Movie
ms -> NonEmpty MovieItem -> Vimeta m (NonEmpty MovieItem)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Movie -> MovieItem
MovieItem (Movie -> MovieItem) -> NonEmpty Movie -> NonEmpty MovieItem
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NonEmpty Movie
ms)
)
MovieItem Movie
movie <- Menu MovieItem
-> Stylized Text -> Stylized Text -> Vimeta m MovieItem
forall (m :: * -> *) a b e.
(MonadByline m, ToStylizedText a, ToStylizedText b,
ToStylizedText e) =>
Menu a -> b -> e -> m a
askWithMenuRepeatedly (NonEmpty MovieItem -> Menu MovieItem
forall a. ToStylizedText a => NonEmpty a -> Menu a
mkMenu NonEmpty MovieItem
movies) Stylized Text
prompt Stylized Text
eprompt
Movie -> Vimeta m ()
forall (m :: * -> *). MonadIO m => Movie -> Vimeta m ()
logID Movie
movie Vimeta m () -> Vimeta m Movie -> Vimeta m Movie
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> TheMovieDB Movie -> Vimeta m Movie
forall (m :: * -> *) a. MonadIO m => TheMovieDB a -> Vimeta m a
tmdb (ItemID -> TheMovieDB Movie
fetchMovie (Movie -> ItemID
movieID Movie
movie))
where
mkMenu :: NonEmpty a -> Menu a
mkMenu NonEmpty a
movies = Stylized Text -> Menu a -> Menu a
forall b a. ToStylizedText b => b -> Menu a -> Menu a
menuBanner (Text -> Stylized Text
text Text
"Choose a movie:") (NonEmpty a -> Menu a
forall a. ToStylizedText a => NonEmpty a -> Menu a
menu NonEmpty a
movies)
searchPrompt :: Stylized Text
searchPrompt = Text -> Stylized Text
text Text
"search (movie name): "
searchErr :: Stylized Text
searchErr = Stylized Text
"please enter a valid search term" Stylized Text -> Stylized Text -> Stylized Text
forall a. Semigroup a => a -> a -> a
<> Color -> Stylized Text
fg Color
red
prompt :: Stylized Text
prompt = Text -> Stylized Text
text Text
"Which is the correct movie? "
eprompt :: Stylized Text
eprompt = Stylized Text
"please choose a valid movie" Stylized Text -> Stylized Text -> Stylized Text
forall a. Semigroup a => a -> a -> a
<> Color -> Stylized Text
fg Color
red
logID :: Movie -> Vimeta m ()
logID Movie
movie =
Text -> Vimeta m ()
forall (m :: * -> *). MonadIO m => Text -> Vimeta m ()
verbose (Text -> Vimeta m ()) -> Text -> Vimeta m ()
forall a b. (a -> b) -> a -> b
$
Text
"using movie ID: "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ItemID -> Text
forall b a. (Show a, IsString b) => a -> b
show (Movie -> ItemID
movieID Movie
movie)