{-

This file is part of the vimeta package. It is subject to the license
terms in the LICENSE file found in the top-level directory of this
distribution and at git://pmade.com/vimeta/LICENSE. No part of the
vimeta package, including this file, may be copied, modified,
propagated, or distributed except according to the terms contained in
the LICENSE file.

-}

-- | Search for a TV series by interacting with the user through the
-- terminal.
module Vimeta.UI.Term.TV
  ( tvSearch,
  )
where

import Byline.Menu
import Network.API.TheMovieDB
import Vimeta.Core
import Vimeta.UI.Common.Util
import Vimeta.UI.Term.Common

newtype TVItem = TVItem TV

instance ToStylizedText TVItem where
  toStylizedText :: TVItem -> Stylized Text
toStylizedText (TVItem TV
series) =
    [Stylized Text] -> Stylized Text
forall a. Monoid a => [a] -> a
mconcat
      [ Text -> Stylized Text
text (TV -> Text
tvName TV
series),
        Text -> Stylized Text
text (Text -> Text
parens (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ Maybe Day -> Maybe Day -> Text
dayRange (TV -> Maybe Day
tvFirstAirDate TV
series) (TV -> Maybe Day
tvLastAirDate TV
series))
      ]

tvSearch :: MonadIO m => Vimeta m TV
tvSearch :: Vimeta m TV
tvSearch = do
  let prompt :: Stylized Text
prompt = Text -> Stylized Text
text Text
"search (series name): "
      mprompt :: Stylized Text
mprompt = Text -> Stylized Text
text Text
"Which is the correct TV series? "
      sprompt :: Stylized Text
sprompt = Stylized Text
"a search term is required" Stylized Text -> Stylized Text -> Stylized Text
forall a. Semigroup a => a -> a -> a
<> Color -> Stylized Text
fg Color
red
      eprompt :: Stylized Text
eprompt = Stylized Text
"please choose a TV series" Stylized Text -> Stylized Text -> Stylized Text
forall a. Semigroup a => a -> a -> a
<> Color -> Stylized Text
fg Color
red
      mkMenu :: NonEmpty TVItem -> Menu TVItem
mkMenu = Stylized Text -> Menu TVItem -> Menu TVItem
forall b a. ToStylizedText b => b -> Menu a -> Menu a
menuBanner (Text -> Stylized Text
text Text
"Choose a TV series:") (Menu TVItem -> Menu TVItem)
-> (NonEmpty TVItem -> Menu TVItem)
-> NonEmpty TVItem
-> Menu TVItem
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty TVItem -> Menu TVItem
forall a. ToStylizedText a => NonEmpty a -> Menu a
menu
      logID :: TV -> Vimeta m ()
logID TV
tv = 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 TV ID: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ItemID -> Text
forall b a. (Show a, IsString b) => a -> b
show (TV -> ItemID
tvID TV
tv)

  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
prompt Maybe Text
forall a. Maybe a
Nothing (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
sprompt)
  NonEmpty TVItem
series <-
    TheMovieDB [TV] -> Vimeta m [TV]
forall (m :: * -> *) a. MonadIO m => TheMovieDB a -> Vimeta m a
tmdb (Text -> TheMovieDB [TV]
searchTV Text
name)
      Vimeta m [TV]
-> ([TV] -> Vimeta m (NonEmpty TVItem))
-> Vimeta m (NonEmpty TVItem)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ( [TV] -> Maybe (NonEmpty TV)
forall a. [a] -> Maybe (NonEmpty a)
nonEmpty ([TV] -> Maybe (NonEmpty TV))
-> (Maybe (NonEmpty TV) -> Vimeta m (NonEmpty TVItem))
-> [TV]
-> Vimeta m (NonEmpty TVItem)
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 TV)
Nothing -> String -> Vimeta m (NonEmpty TVItem)
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 TV
xs -> NonEmpty TVItem -> Vimeta m (NonEmpty TVItem)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (TV -> TVItem
TVItem (TV -> TVItem) -> NonEmpty TV -> NonEmpty TVItem
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NonEmpty TV
xs)
          )
  TVItem TV
tv <- Menu TVItem -> Stylized Text -> Stylized Text -> Vimeta m TVItem
forall (m :: * -> *) a b e.
(MonadByline m, ToStylizedText a, ToStylizedText b,
 ToStylizedText e) =>
Menu a -> b -> e -> m a
askWithMenuRepeatedly (NonEmpty TVItem -> Menu TVItem
mkMenu NonEmpty TVItem
series) Stylized Text
mprompt Stylized Text
eprompt
  TV -> Vimeta m ()
forall (m :: * -> *). MonadIO m => TV -> Vimeta m ()
logID TV
tv Vimeta m () -> Vimeta m TV -> Vimeta m TV
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> TheMovieDB TV -> Vimeta m TV
forall (m :: * -> *) a. MonadIO m => TheMovieDB a -> Vimeta m a
tmdb (ItemID -> TheMovieDB TV
fetchFullTVSeries (TV -> ItemID
tvID TV
tv))