-- |
--
-- Copyright:
--   This file is part of the package vimeta. It is subject to the
--   license terms in the LICENSE file found in the top-level
--   directory of this distribution and at:
--
--     https://github.com/pjones/vimeta
--
--   No part of this package, including this file, may be copied,
--   modified, propagated, or distributed except according to the terms
--   contained in the LICENSE file.
--
-- License: BSD-2-Clause
module Vimeta.UI.CommandLine.TV
  ( Options,
    optionsParser,
    run,
  )
where

import Network.API.TheMovieDB
import Options.Applicative
import Vimeta.Core
import Vimeta.UI.CommandLine.Common
import Vimeta.UI.Common.TV
import Vimeta.UI.Term.TV

data Options = Options
  { Options -> Maybe ItemID
optsTVID :: Maybe ItemID,
    Options -> Maybe ItemID
optsStartSeason :: Maybe Int,
    Options -> Maybe ItemID
optsStartEpisode :: Maybe Int,
    Options -> Maybe FilePath
optsMappingFile :: Maybe FilePath,
    Options -> [FilePath]
optsFiles :: [FilePath],
    Options -> CommonOptions
optsCommon :: CommonOptions
  }

optionsParser :: Parser Options
optionsParser :: Parser Options
optionsParser =
  Maybe ItemID
-> Maybe ItemID
-> Maybe ItemID
-> Maybe FilePath
-> [FilePath]
-> CommonOptions
-> Options
Options (Maybe ItemID
 -> Maybe ItemID
 -> Maybe ItemID
 -> Maybe FilePath
 -> [FilePath]
 -> CommonOptions
 -> Options)
-> Parser (Maybe ItemID)
-> Parser
     (Maybe ItemID
      -> Maybe ItemID
      -> Maybe FilePath
      -> [FilePath]
      -> CommonOptions
      -> Options)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ItemID -> Parser (Maybe ItemID)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (ReadM ItemID -> Mod OptionFields ItemID -> Parser ItemID
forall a. ReadM a -> Mod OptionFields a -> Parser a
option ReadM ItemID
forall a. Read a => ReadM a
auto Mod OptionFields ItemID
forall a. Mod OptionFields a
infoTVID)
    Parser
  (Maybe ItemID
   -> Maybe ItemID
   -> Maybe FilePath
   -> [FilePath]
   -> CommonOptions
   -> Options)
-> Parser (Maybe ItemID)
-> Parser
     (Maybe ItemID
      -> Maybe FilePath -> [FilePath] -> CommonOptions -> Options)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser ItemID -> Parser (Maybe ItemID)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (ReadM ItemID -> Mod OptionFields ItemID -> Parser ItemID
forall a. ReadM a -> Mod OptionFields a -> Parser a
option ReadM ItemID
forall a. Read a => ReadM a
auto Mod OptionFields ItemID
forall a. Mod OptionFields a
infoStartSeason)
    Parser
  (Maybe ItemID
   -> Maybe FilePath -> [FilePath] -> CommonOptions -> Options)
-> Parser (Maybe ItemID)
-> Parser
     (Maybe FilePath -> [FilePath] -> CommonOptions -> Options)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser ItemID -> Parser (Maybe ItemID)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (ReadM ItemID -> Mod OptionFields ItemID -> Parser ItemID
forall a. ReadM a -> Mod OptionFields a -> Parser a
option ReadM ItemID
forall a. Read a => ReadM a
auto Mod OptionFields ItemID
forall a. Mod OptionFields a
infoStartEpisode)
    Parser (Maybe FilePath -> [FilePath] -> CommonOptions -> Options)
-> Parser (Maybe FilePath)
-> Parser ([FilePath] -> CommonOptions -> Options)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser FilePath -> Parser (Maybe FilePath)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Mod OptionFields FilePath -> Parser FilePath
forall s. IsString s => Mod OptionFields s -> Parser s
strOption Mod OptionFields FilePath
forall a. Mod OptionFields a
infoMappingFile)
    Parser ([FilePath] -> CommonOptions -> Options)
-> Parser [FilePath] -> Parser (CommonOptions -> Options)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser FilePath -> Parser [FilePath]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many (ReadM FilePath -> Mod ArgumentFields FilePath -> Parser FilePath
forall a. ReadM a -> Mod ArgumentFields a -> Parser a
argument ReadM FilePath
forall s. IsString s => ReadM s
str (FilePath -> Mod ArgumentFields FilePath
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
metavar FilePath
"[FILE...]"))
    Parser (CommonOptions -> Options)
-> Parser CommonOptions -> Parser Options
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser CommonOptions
commonOptions
  where
    infoTVID :: Mod OptionFields a
infoTVID =
      Char -> Mod OptionFields a
forall (f :: * -> *) a. HasName f => Char -> Mod f a
short Char
'i' Mod OptionFields a -> Mod OptionFields a -> Mod OptionFields a
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields a
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
long FilePath
"id" Mod OptionFields a -> Mod OptionFields a -> Mod OptionFields a
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields a
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
metavar FilePath
"ID"
        Mod OptionFields a -> Mod OptionFields a -> Mod OptionFields a
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields a
forall (f :: * -> *) a. FilePath -> Mod f a
help FilePath
"Series ID assigned by TheMovieDB.org"
    infoStartSeason :: Mod OptionFields a
infoStartSeason =
      Char -> Mod OptionFields a
forall (f :: * -> *) a. HasName f => Char -> Mod f a
short Char
's' Mod OptionFields a -> Mod OptionFields a -> Mod OptionFields a
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields a
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
long FilePath
"season" Mod OptionFields a -> Mod OptionFields a -> Mod OptionFields a
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields a
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
metavar FilePath
"NUM"
        Mod OptionFields a -> Mod OptionFields a -> Mod OptionFields a
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields a
forall (f :: * -> *) a. FilePath -> Mod f a
help FilePath
"Starting season number"
    infoStartEpisode :: Mod OptionFields a
infoStartEpisode =
      Char -> Mod OptionFields a
forall (f :: * -> *) a. HasName f => Char -> Mod f a
short Char
'e' Mod OptionFields a -> Mod OptionFields a -> Mod OptionFields a
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields a
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
long FilePath
"episode" Mod OptionFields a -> Mod OptionFields a -> Mod OptionFields a
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields a
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
metavar FilePath
"NUM"
        Mod OptionFields a -> Mod OptionFields a -> Mod OptionFields a
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields a
forall (f :: * -> *) a. FilePath -> Mod f a
help FilePath
"Starting episode number"
    infoMappingFile :: Mod OptionFields a
infoMappingFile =
      Char -> Mod OptionFields a
forall (f :: * -> *) a. HasName f => Char -> Mod f a
short Char
'm' Mod OptionFields a -> Mod OptionFields a -> Mod OptionFields a
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields a
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
long FilePath
"map" Mod OptionFields a -> Mod OptionFields a -> Mod OptionFields a
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields a
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
metavar FilePath
"FILE"
        Mod OptionFields a -> Mod OptionFields a -> Mod OptionFields a
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields a
forall (f :: * -> *) a. FilePath -> Mod f a
help FilePath
"File to map files to seasons/episodes"

run :: Options -> IO (Either String ())
run :: Options -> IO (Either FilePath ())
run Options
opts = (Config -> Config) -> Vimeta IO () -> IO (Either FilePath ())
forall (m :: * -> *) a.
(MonadIO m, MonadMask m) =>
(Config -> Config) -> Vimeta m a -> m (Either FilePath a)
execVimeta (CommonOptions -> Config -> Config
updateConfig (CommonOptions -> Config -> Config)
-> CommonOptions -> Config -> Config
forall a b. (a -> b) -> a -> b
$ Options -> CommonOptions
optsCommon Options
opts) (Vimeta IO () -> IO (Either FilePath ()))
-> Vimeta IO () -> IO (Either FilePath ())
forall a b. (a -> b) -> a -> b
$ do
  TV
tv <- case Options -> Maybe ItemID
optsTVID Options
opts of
    Maybe ItemID
Nothing -> Vimeta IO TV
forall (m :: * -> *). MonadIO m => Vimeta m TV
tvSearch
    Just ItemID
n -> TheMovieDB TV -> Vimeta IO TV
forall (m :: * -> *) a. MonadIO m => TheMovieDB a -> Vimeta m a
tmdb (ItemID -> TheMovieDB TV
fetchFullTVSeries ItemID
n)

  case Options -> Maybe FilePath
optsMappingFile Options
opts of
    Maybe FilePath
Nothing -> Options -> TV -> Vimeta IO ()
forall (m :: * -> *). MonadIO m => Options -> TV -> Vimeta m ()
fromFiles Options
opts TV
tv
    Just FilePath
fn -> Options -> TV -> FilePath -> Vimeta IO ()
forall (m :: * -> *).
MonadIO m =>
Options -> TV -> FilePath -> Vimeta m ()
fromMappingFile Options
opts TV
tv FilePath
fn

fromFiles :: (MonadIO m) => Options -> TV -> Vimeta m ()
fromFiles :: Options -> TV -> Vimeta m ()
fromFiles Options
opts TV
tv = case (Options -> Maybe ItemID
optsStartSeason Options
opts, Options -> Maybe ItemID
optsStartEpisode Options
opts) of
  (Just ItemID
s, Maybe ItemID
Nothing) -> TV -> EpisodeSpec -> [FilePath] -> Vimeta m ()
forall (m :: * -> *).
MonadIO m =>
TV -> EpisodeSpec -> [FilePath] -> Vimeta m ()
tagWithFileOrder TV
tv (ItemID -> ItemID -> EpisodeSpec
EpisodeSpec ItemID
s ItemID
1) (Options -> [FilePath]
optsFiles Options
opts)
  (Just ItemID
s, Just ItemID
e) -> TV -> EpisodeSpec -> [FilePath] -> Vimeta m ()
forall (m :: * -> *).
MonadIO m =>
TV -> EpisodeSpec -> [FilePath] -> Vimeta m ()
tagWithFileOrder TV
tv (ItemID -> ItemID -> EpisodeSpec
EpisodeSpec ItemID
s ItemID
e) (Options -> [FilePath]
optsFiles Options
opts)
  (Maybe ItemID
_, Maybe ItemID
_) -> FilePath -> Vimeta m ()
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError FilePath
"please use the --season option"

fromMappingFile :: (MonadIO m) => Options -> TV -> FilePath -> Vimeta m ()
fromMappingFile :: Options -> TV -> FilePath -> Vimeta m ()
fromMappingFile Options
opts TV
tv FilePath
filename = do
  Bool -> Vimeta m () -> Vimeta m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([FilePath] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([FilePath] -> Bool) -> [FilePath] -> Bool
forall a b. (a -> b) -> a -> b
$ Options -> [FilePath]
optsFiles Options
opts) (Vimeta m () -> Vimeta m ()) -> Vimeta m () -> Vimeta m ()
forall a b. (a -> b) -> a -> b
$
    FilePath -> Vimeta m ()
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError FilePath
"don't give file arguments when using a mapping file"

  TV -> FilePath -> Vimeta m ()
forall (m :: * -> *). MonadIO m => TV -> FilePath -> Vimeta m ()
tagWithMappingFile TV
tv FilePath
filename