-- hokey.hs: hOpenPGP key tool
-- Copyright © 2013-2026  Clint Adams
--
-- vim: softtabstop=4:shiftwidth=4:expandtab
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Affero General Public License as
-- published by the Free Software Foundation, either version 3 of the
-- License, or (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU Affero General Public License for more details.
--
-- You should have received a copy of the GNU Affero General Public License
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.

{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeApplications #-}

import HOpenPGP.Tools.Common.Common (banner, versioner, warranty)

import Options.Applicative.Builder
  ( command
  , footerDoc
  , headerDoc
  , info
  , prefs
  , progDesc
  , showHelpOnError
  )
import Options.Applicative.Extra (customExecParser, helper, hsubparser)
import Options.Applicative.Types (Parser)
import System.IO
  ( BufferMode(..)
  , Handle
  , hFlush
  , hSetBuffering
  , stderr
  )
import Prettyprinter (hardline)
import qualified Prettyprinter.Render.Terminal as PPA
import HOpenPGP.Tools.Hokey.Options
  ( FetchOptions
  , InjectSSHAgentOptions
  , LintOptions
  , fetchO
  , injectSSHAgentO
  , lintO
  )
import HOpenPGP.Tools.Hokey.Canonicalize (doCanonicalize)
import HOpenPGP.Tools.Hokey.Fetch (doFetch)
import HOpenPGP.Tools.Hokey.InjectSSHAgent (doInjectSSHAgent)
import HOpenPGP.Tools.Hokey.Lint (doLint)

data Command
  = CmdLint LintOptions
  | CmdCanonicalize
  | CmdFetch FetchOptions
  | CmdInjectSSHAgent InjectSSHAgentOptions

dispatch :: Command -> IO ()
dispatch (CmdFetch o) = banner' stderr >> hFlush stderr >> doFetch o
dispatch (CmdLint o) = banner' stderr >> hFlush stderr >> doLint o
dispatch CmdCanonicalize = banner' stderr >> hFlush stderr >> doCanonicalize
dispatch (CmdInjectSSHAgent o) =
  banner' stderr >> hFlush stderr >> doInjectSSHAgent o

main :: IO ()
main = do
  hSetBuffering stderr LineBuffering
  customExecParser
    (prefs showHelpOnError)
    (info
       (helper <*> versioner "hokey" <*> cmd)
       (headerDoc (Just (banner "hokey")) <>
        progDesc "hOpenPGP Key utility" <>
        footerDoc (Just (warranty "hokey")))) >>=
    dispatch

cmd :: Parser Command
cmd =
  hsubparser
    (command
       "canonicalize"
       (info
          (pure CmdCanonicalize)
          (progDesc "arrange key components in a canonical ordering")) <>
     command
       "fetch"
       (info
          (CmdFetch <$> fetchO)
          (progDesc "fetch key(s) via HKP or WKD")) <>
     command
       "inject-ssh-agent"
       (info
          (CmdInjectSSHAgent <$> injectSSHAgentO)
          (progDesc "Read exported secret key bytes, pick an auth-capable subkey, and add it to ssh-agent")) <>
     command
       "lint"
       (info (CmdLint <$> lintO) (progDesc "check key(s) for 'best practices'")))

banner' :: Handle -> IO ()
banner' h =
  PPA.hPutDoc h (banner "hokey" <> hardline <> warranty "hokey" <> hardline)

