A cli database for some FFX stuff
{-# LANGUAGE TypeApplications #-}

module Options.Primer
    ( ListOptions (..)
    , PrimerCommand (..)
    , commands
    ) where

import           Options.Applicative
import qualified Options.Parsers     as Parser

import           Data.Bifunctor      (bimap, first)
import           Data.Either.Extra   (maybeToEither)

import           Control.Monad

import           Text.Read           (readEither)

import           AlBhed              (Primer, Volume)
import qualified AlBhed
import           Location            (Location)
import qualified Location

data ListOptions = OneLine | MultiLine
    deriving (Show)

data PrimerCommand =
    Add Volume Location
    | New Volume Char Char Location
    | List ListOptions
    deriving (Show)

commands :: Parser PrimerCommand
commands = hsubparser
    ( command "add" (info addCommand (progDesc "Add a primer location to the index"))
    <> command "new" (info newCommand (progDesc "Add a new AlBhed Primer to the index"))
    <> command "ls" (info listCommand (progDesc "List all AlBhed Primers in the index"))
    )

listCommand :: Parser PrimerCommand
listCommand = List <$> listOpts
    where
        listOpts = flag MultiLine OneLine (long "oneline" <> short '1' <> help "Print all primers on one line if possible")

newCommand :: Parser PrimerCommand
newCommand = New <$> volume <*> char "FROM" <*> char "TO" <*> location
    where
        char = argument Parser.singleChar . metavar

addCommand :: Parser PrimerCommand
addCommand = Add <$> volume <*> location

volume :: Parser Volume
volume = argument parseVolume (metavar "VOLUME")

location :: Parser Location
location = Location.Location
    <$> argument Parser.printableText (metavar "AREA")
    <*> optional (argument Parser.printableText (metavar "SECTION"))

parseVolume :: ReadM Volume
parseVolume = eitherReader $
    (first parseError . input) >=> volume
    where
        parseError = const "Failed to parse volume number"
        input = readEither @Int
        volume = maybeToEither "Volume must be 1 to 26" . AlBhed.toVolume