<commit_before>{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies    #-}

module Main where

import qualified Control.Exception   as Exception
import           Data.Acid
import           Data.Maybe          (fromMaybe)
import qualified Data.Text           as T
import qualified Data.Text.IO        as T
import qualified Data.Version        as Version
import           Options.Applicative
import qualified Paths_hasken        as Meta
import           System.Environment  (getArgs, getEnv)

import           Config
import           Local.Document
import           Local.Sync          (createDoc, fromDatabaseDoc)
import qualified Remote.Client       as Client
import qualified Remote.Main         as Server

$(makeAcidic ''Database [
  'addDocument,
  'viewDocuments,
  'searchDocuments
  ])


upsert docs database = undefined
  -- fmap (\doc -> update database (AddDocument (fromDatabaseDoc doc))) docs

doSync localDocs database = do
  mapM_ createDoc localDocs
  remoteDocs <- Client.listDocuments
  -- upsert remoteDocs database
  createCheckpoint database
  putStrLn $ "synced: " ++ show remoteDocs



deletePrompt :: IO ()
deletePrompt = putStrLn "asdf"

display :: [Document] -> IO ()
display docs = do
  showTagsSetting <- showTags <$> localConfig
  if showTagsSetting
     then mapM_ displayDocWithTags docs
     else mapM_ displayDoc docs

showTagsParser :: Parser Bool
showTagsParser =
  switch (
    long "show-tags"
    <> help "show tags when displaying documents" )

optParser :: Parser Options
optParser =
  Options
  <$> switch (short 'v' <> long "version" <> help "Show version and exit")
  <*> showTagsParser
  <*> commandParser

parseAdd :: Parser Command
parseAdd =
  Add <$> some (argument str (metavar "Title Tag1,Tag2 Content and stuff"))

parseSearch :: Parser Command
parseSearch =
  Search <$> some (argument str (metavar "QUERIES.."))

parseList :: Parser Command
parseList = List <$> optional (argument str (metavar "LIMIT"))

withInfo :: Parser a -> String -> ParserInfo a
withInfo opts desc = info (helper <*> opts) $ progDesc desc

commandParser :: Parser Command
commandParser =
  subparser $
       command "add" (parseAdd `withInfo` "Add a document to the local storage")
    <> command "search" (parseSearch `withInfo` "search the local docs")
    <> command "list" (parseList `withInfo` "list local docs (defaults to limit 10)")
    <> command "sync" (pure Sync `withInfo` "sync with the remote")
    <> command "serve" (pure Serve `withInfo` "serve an instance of the remote component")

data Options
  = Options
  { optShowVersion :: Bool
  , optShowTags    :: Bool
  , optCommand     :: Command }

data Command
  = Add [String]
  | Search [String]
  | List (Maybe String)
  | Sync
  | Serve

showVersion =
  putStrLn $ "Version " <> Version.showVersion Meta.version

run :: Options -> IO ()
run opts =
  if optShowVersion opts
  then showVersion
  else run' opts

withLocalDatabase = Exception.bracket openDb closeAcidState
  where
    openDb = do
      loc <- localStorageLocation
      openLocalStateFrom loc (Database [])

run' :: Options -> IO ()
run' opts = withLocalDatabase $ \database ->
  case optCommand opts of
    Add passedArgs -> do
      let newDoc = buildDocument passedArgs
      update database (AddDocument newDoc)
    Search qs ->
      query database (SearchDocuments qs) >>= display
    Sync -> do
      documents <- query database (ViewDocuments 1000)
      doSync documents database
    Serve -> do
      closeAcidState database
      Server.main
    List i ->
      case i of
        Nothing -> query database (ViewDocuments 10) >>= display
        Just n -> query database (ViewDocuments (read n :: Int)) >>= display

main :: IO ()
main = execParser opts >>= run
  where
    opts =
      info (helper <*> optParser)
      ( fullDesc
      <> progDesc "tagged local storage with a sync option"
      <> header "create and tag documents for searchable recall"
      )<commit_msg>fix version flag<commit_after>{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies    #-}

module Main where

import qualified Control.Exception   as Exception
import           Data.Acid
import           Data.Maybe          (fromMaybe)
import qualified Data.Text           as T
import qualified Data.Text.IO        as T
import qualified Data.Version        as Version
import           Options.Applicative
import qualified Paths_hasken        as Meta
import           System.Environment  (getArgs, getEnv)

import           Config
import           Local.Document
import           Local.Sync          (createDoc, fromDatabaseDoc)
import qualified Remote.Client       as Client
import qualified Remote.Main         as Server

$(makeAcidic ''Database [
  'addDocument,
  'viewDocuments,
  'searchDocuments
  ])


upsert docs database = undefined
  -- fmap (\doc -> update database (AddDocument (fromDatabaseDoc doc))) docs

doSync localDocs database = do
  mapM_ createDoc localDocs
  remoteDocs <- Client.listDocuments
  -- upsert remoteDocs database
  createCheckpoint database
  putStrLn $ "synced: " ++ show remoteDocs

display :: [Document] -> IO ()
display docs = do
  showTagsSetting <- showTags <$> localConfig
  if showTagsSetting
     then mapM_ displayDocWithTags docs
     else mapM_ displayDoc docs

showTagsParser :: Parser Bool
showTagsParser =
  switch (
    long "show-tags" <> help "show tags when displaying documents" )

optParser :: Parser Options
optParser =
  Options
  <$> switch (long "version" <> help "Show version and exit")
  <*> showTagsParser
  <*> commandParser

parseAdd :: Parser Command
parseAdd =
  Add <$> some (argument str (metavar "Title Tag1,Tag2 Content and stuff"))

parseSearch :: Parser Command
parseSearch =
  Search <$> some (argument str (metavar "QUERIES.."))

parseList :: Parser Command
parseList = List <$> optional (argument str (metavar "LIMIT"))

withInfo :: Parser a -> String -> ParserInfo a
withInfo opts desc = info (helper <*> opts) $ progDesc desc

commandParser :: Parser (Maybe Command)
commandParser = optional $ subparser $
     command "add" (parseAdd `withInfo` "Add a document to the local storage")
  <> command "search" (parseSearch `withInfo` "search the local docs")
  <> command "list" (parseList `withInfo` "list local docs (defaults to limit 10)")
  <> command "sync" (pure Sync `withInfo` "sync with the remote")
  <> command "serve" (pure Serve `withInfo` "serve an instance of the remote component")

data Options
  = Options
  { optShowVersion :: Bool
  , optShowTags    :: Bool
  , optCommand     :: Maybe Command }
  deriving (Show)

data Command
  = Add [String]
  | Search [String]
  | List (Maybe String)
  | Sync
  | Serve
  deriving (Show)

run :: Options -> IO ()
run opts =
  if optShowVersion opts
  then showVersion
  else run' opts

showVersion = putStrLn $ "Version " <> Version.showVersion Meta.version

withLocalDatabase = Exception.bracket openDb closeAcidState
  where
    openDb = do
      loc <- localStorageLocation
      openLocalStateFrom loc (Database [])

run' :: Options -> IO ()
run' opts =
  case optCommand opts of
    Nothing -> error "should not reach this"
    Just cmd -> processCmd cmd

processCmd :: Command -> IO ()
processCmd cmd = withLocalDatabase $ \database ->
  case cmd of
    Add passedArgs -> do
      let newDoc = buildDocument passedArgs
      update database (AddDocument newDoc)
    Search qs ->
      query database (SearchDocuments qs) >>= display
    Sync -> do
      documents <- query database (ViewDocuments 1000)
      doSync documents database
    Serve -> do
      closeAcidState database
      Server.main
    List i ->
      case i of
        Nothing -> query database (ViewDocuments 10) >>= display
        Just n -> query database (ViewDocuments (read n :: Int)) >>= display

main :: IO ()
main = execParser opts >>= run
  where
    opts =
      info (helper <*> optParser)
      ( fullDesc
      <> progDesc "tagged local storage with a sync option"
      <> header "create and tag documents for searchable recall"
      )
{'fraction_non_alphanumeric': 0.09096580983279261, 'fraction_numerical': 0.0024956326428749688, 'mean_word_length': 3.070594210259015, 'pattern_counts': {'":': 0, '<': 48, '<?xml version=': 0, '>': 87, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1024039', 'n_tokens_mistral': 2342, 'n_tokens_neox': 2235, 'n_words': 814}