A cli database for some FFX stuff
{-# LANGUAGE DeriveAnyClass             #-}
{-# LANGUAGE DeriveGeneric              #-}
{-# LANGUAGE DeriveTraversable          #-}
{-# LANGUAGE DerivingStrategies         #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE GeneralisedNewtypeDeriving #-}
{-# LANGUAGE PolyKinds                  #-}
{-# LANGUAGE RecordWildCards            #-}

module Options
    ( Build (..)
    , Command (..)
    , Config (..)
    , Run (..)
    , configBuild
    , mainOpts
    ) where

import           Options.Applicative

import           Data.Maybe
import           Data.Monoid

import           Generics.Deriving.Monoid
import           Generics.Deriving.Semigroup

import           System.FilePath

import           Options.Primer              (PrimerCommand)
import qualified Options.Primer              as PrimerOptions

import           GHC.Generics

data Command =
    Primer PrimerCommand
    deriving (Show)

data Config select = Config
    { dataFile :: select Last FilePath
    }
    deriving stock (Generic)

newtype Build f a = Build { fromBuild :: f a }
    deriving stock (Show, Eq, Ord, Functor, Traversable, Foldable, Generic)
    deriving newtype (Semigroup, Monoid)
    deriving anyclass (GSemigroup, GMonoid)

newtype Run f a = Run { fromRun :: a }
    deriving stock (Show, Eq, Ord, Functor, Traversable, Foldable)

instance Semigroup (Config Build) where
    (<>) = gsappenddefault

instance Monoid (Config Build) where
    mempty = memptydefault

(!<-) :: (f a -> b) -> Build f a -> Run f b
(!<-) f = Run . f . fromBuild

infix 1 !<-

configBuild :: FilePath -> Config Build -> Config Run
configBuild datadir Config {..} = Config
    { dataFile = fromMaybe (datadir </> "db.json") . getLast !<- dataFile
    }

mainOpts :: Parser (Config Build, Command)
mainOpts = (,) <$> configOpts <*> mainCommand

configOpts :: Parser (Config Build)
configOpts = Config <$> dataFileOpt

dataFileOpt :: Parser (Build Last FilePath)
dataFileOpt = Build . Last <$> optional (strOption
    (long "data-file"
    <> short 'f'
    <> metavar "FILE"
    <> help "The datafile to read from, if none is given it will default to DATA_HOME of the XDG Base Directory implementation"))

mainCommand :: Parser Command
mainCommand = hsubparser
    ( command "primer" (info (Primer <$> PrimerOptions.commands) (progDesc "Work with AlBhed Primers")))