module Unison.Codebase.Editor.HandleInput.History (handleHistory) where

import Data.Map qualified as Map
import U.Codebase.HashTags
import U.Codebase.Sqlite.HistoryComment (HistoryComment (..))
import U.Codebase.Sqlite.Queries qualified as Q
import Unison.Cli.Monad qualified as Cli
import Unison.Cli.MonadUtils qualified as Cli
import Unison.Codebase qualified as Codebase
import Unison.Codebase.Branch
import Unison.Codebase.Branch qualified as Branch
import Unison.Codebase.Branch.Names qualified as Branch
import Unison.Codebase.Causal qualified as Causal
import Unison.Codebase.Editor.Input
import Unison.Codebase.Editor.Output
import Unison.Codebase.Path (Path')
import Unison.NamesWithHistory qualified as Names
import Unison.Prelude

handleHistory :: Maybe Int -> Maybe Int -> BranchIdG Path' -> Cli.Cli ()
handleHistory :: Maybe Int -> Maybe Int -> BranchIdG Path' -> Cli ()
handleHistory Maybe Int
resultsCap Maybe Int
diffCap BranchIdG Path'
from = do
  Branch IO
branch <-
    case BranchIdG Path'
from of
      BranchAtSCH ShortCausalHash
hash -> ShortCausalHash -> Cli (Branch IO)
Cli.resolveShortCausalHash ShortCausalHash
hash
      BranchAtPath Path'
path' -> do
        ProjectPath
pp <- Path' -> Cli ProjectPath
Cli.resolvePath' Path'
path'
        ProjectPath -> Cli (Branch IO)
Cli.getBranchFromProjectPath ProjectPath
pp
      BranchAtProjectPath ProjectPath
pp -> ProjectPath -> Cli (Branch IO)
Cli.getBranchFromProjectPath ProjectPath
pp
  Int
schLength <- Transaction Int -> Cli Int
forall a. Transaction a -> Cli a
Cli.runTransaction Transaction Int
Codebase.branchHashLength
  NumberedOutput
history <- Int
-> Int
-> Branch IO
-> [(CausalHash, Maybe (HistoryComment () ()), Diff)]
-> Cli NumberedOutput
doHistory Int
schLength Int
0 Branch IO
branch []
  NumberedOutput -> Cli ()
Cli.respondNumbered NumberedOutput
history
  where
    doHistory :: Int -> Int -> Branch IO -> [(CausalHash, Maybe (HistoryComment () ()), Names.Diff)] -> Cli.Cli NumberedOutput
    doHistory :: Int
-> Int
-> Branch IO
-> [(CausalHash, Maybe (HistoryComment () ()), Diff)]
-> Cli NumberedOutput
doHistory Int
schLength !Int
n Branch IO
b [(CausalHash, Maybe (HistoryComment () ()), Diff)]
acc =
      if Bool -> (Int -> Bool) -> Maybe Int -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False (Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=) Maybe Int
resultsCap
        then do
          Maybe (HistoryComment () ())
mayComment <- CausalHash -> Cli (Maybe (HistoryComment () ()))
getComment (CausalHash -> Cli (Maybe (HistoryComment () ())))
-> CausalHash -> Cli (Maybe (HistoryComment () ()))
forall a b. (a -> b) -> a -> b
$ Branch IO -> CausalHash
forall (m :: * -> *). Branch m -> CausalHash
Branch.headHash Branch IO
b
          NumberedOutput -> Cli NumberedOutput
forall a. a -> Cli a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe Int
-> Int
-> [(CausalHash, Maybe (HistoryComment () ()), Diff)]
-> (Maybe (HistoryComment () ()), HistoryTail)
-> NumberedOutput
History Maybe Int
diffCap Int
schLength [(CausalHash, Maybe (HistoryComment () ()), Diff)]
acc (Maybe (HistoryComment () ())
mayComment, CausalHash -> Int -> HistoryTail
PageEnd (Branch IO -> CausalHash
forall (m :: * -> *). Branch m -> CausalHash
Branch.headHash Branch IO
b) Int
n))
        else case Branch IO -> UnwrappedBranch IO
forall (m :: * -> *). Branch m -> UnwrappedBranch m
Branch._history Branch IO
b of
          Causal.One {} -> do
            Maybe (HistoryComment () ())
mayComment <- CausalHash -> Cli (Maybe (HistoryComment () ()))
getComment (CausalHash -> Cli (Maybe (HistoryComment () ())))
-> CausalHash -> Cli (Maybe (HistoryComment () ()))
forall a b. (a -> b) -> a -> b
$ Branch IO -> CausalHash
forall (m :: * -> *). Branch m -> CausalHash
Branch.headHash Branch IO
b
            NumberedOutput -> Cli NumberedOutput
forall a. a -> Cli a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe Int
-> Int
-> [(CausalHash, Maybe (HistoryComment () ()), Diff)]
-> (Maybe (HistoryComment () ()), HistoryTail)
-> NumberedOutput
History Maybe Int
diffCap Int
schLength [(CausalHash, Maybe (HistoryComment () ()), Diff)]
acc (Maybe (HistoryComment () ())
mayComment, CausalHash -> HistoryTail
EndOfLog (CausalHash -> HistoryTail) -> CausalHash -> HistoryTail
forall a b. (a -> b) -> a -> b
$ Branch IO -> CausalHash
forall (m :: * -> *). Branch m -> CausalHash
Branch.headHash Branch IO
b))
          Causal.Merge CausalHash
_ HashFor (Branch0 IO)
_ Branch0 IO
_ Map CausalHash (IO (UnwrappedBranch IO))
tails -> do
            Maybe (HistoryComment () ())
mayComment <- CausalHash -> Cli (Maybe (HistoryComment () ()))
getComment (CausalHash -> Cli (Maybe (HistoryComment () ())))
-> CausalHash -> Cli (Maybe (HistoryComment () ()))
forall a b. (a -> b) -> a -> b
$ Branch IO -> CausalHash
forall (m :: * -> *). Branch m -> CausalHash
Branch.headHash Branch IO
b
            NumberedOutput -> Cli NumberedOutput
forall a. a -> Cli a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe Int
-> Int
-> [(CausalHash, Maybe (HistoryComment () ()), Diff)]
-> (Maybe (HistoryComment () ()), HistoryTail)
-> NumberedOutput
History Maybe Int
diffCap Int
schLength [(CausalHash, Maybe (HistoryComment () ()), Diff)]
acc (Maybe (HistoryComment () ())
mayComment, CausalHash -> [CausalHash] -> HistoryTail
MergeTail (Branch IO -> CausalHash
forall (m :: * -> *). Branch m -> CausalHash
Branch.headHash Branch IO
b) ([CausalHash] -> HistoryTail) -> [CausalHash] -> HistoryTail
forall a b. (a -> b) -> a -> b
$ Map CausalHash (IO (UnwrappedBranch IO)) -> [CausalHash]
forall k a. Map k a -> [k]
Map.keys Map CausalHash (IO (UnwrappedBranch IO))
tails))
          Causal.Cons CausalHash
_ HashFor (Branch0 IO)
_ Branch0 IO
_ (CausalHash, IO (UnwrappedBranch IO))
tail -> do
            Branch IO
b' <- IO (Branch IO) -> Cli (Branch IO)
forall a. IO a -> Cli a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Branch IO) -> Cli (Branch IO))
-> IO (Branch IO) -> Cli (Branch IO)
forall a b. (a -> b) -> a -> b
$ (UnwrappedBranch IO -> Branch IO)
-> IO (UnwrappedBranch IO) -> IO (Branch IO)
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap UnwrappedBranch IO -> Branch IO
forall (m :: * -> *). UnwrappedBranch m -> Branch m
Branch.Branch (IO (UnwrappedBranch IO) -> IO (Branch IO))
-> IO (UnwrappedBranch IO) -> IO (Branch IO)
forall a b. (a -> b) -> a -> b
$ (CausalHash, IO (UnwrappedBranch IO)) -> IO (UnwrappedBranch IO)
forall a b. (a, b) -> b
snd (CausalHash, IO (UnwrappedBranch IO))
tail
            let causalHash :: CausalHash
causalHash = Branch IO -> CausalHash
forall (m :: * -> *). Branch m -> CausalHash
Branch.headHash Branch IO
b
            Maybe (HistoryComment () ())
mayComment <- CausalHash -> Cli (Maybe (HistoryComment () ()))
getComment CausalHash
causalHash
            let elem :: (CausalHash, Maybe (HistoryComment () ()), Diff)
elem = (CausalHash
causalHash, Maybe (HistoryComment () ())
mayComment, Branch IO -> Branch IO -> Diff
forall (m :: * -> *). Branch m -> Branch m -> Diff
Branch.namesDiff Branch IO
b' Branch IO
b)
            Int
-> Int
-> Branch IO
-> [(CausalHash, Maybe (HistoryComment () ()), Diff)]
-> Cli NumberedOutput
doHistory Int
schLength (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Branch IO
b' ((CausalHash, Maybe (HistoryComment () ()), Diff)
elem (CausalHash, Maybe (HistoryComment () ()), Diff)
-> [(CausalHash, Maybe (HistoryComment () ()), Diff)]
-> [(CausalHash, Maybe (HistoryComment () ()), Diff)]
forall a. a -> [a] -> [a]
: [(CausalHash, Maybe (HistoryComment () ()), Diff)]
acc)
    getComment :: CausalHash -> Cli.Cli (Maybe (HistoryComment () ()))
    getComment :: CausalHash -> Cli (Maybe (HistoryComment () ()))
getComment CausalHash
ch = Transaction (Maybe (HistoryComment () ()))
-> Cli (Maybe (HistoryComment () ()))
forall a. Transaction a -> Cli a
Cli.runTransaction (Transaction (Maybe (HistoryComment () ()))
 -> Cli (Maybe (HistoryComment () ())))
-> Transaction (Maybe (HistoryComment () ()))
-> Cli (Maybe (HistoryComment () ()))
forall a b. (a -> b) -> a -> b
$ do
      CausalHashId
causalHashId <- CausalHash -> Transaction CausalHashId
Q.expectCausalHashIdByCausalHash CausalHash
ch
      CausalHashId
-> Transaction
     (Maybe (HistoryComment CausalHashId HistoryCommentId))
Q.getLatestCausalComment CausalHashId
causalHashId
        Transaction (Maybe (HistoryComment CausalHashId HistoryCommentId))
-> (Maybe (HistoryComment CausalHashId HistoryCommentId)
    -> Maybe (HistoryComment () ()))
-> Transaction (Maybe (HistoryComment () ()))
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> (HistoryComment CausalHashId HistoryCommentId
 -> HistoryComment () ())
-> Maybe (HistoryComment CausalHashId HistoryCommentId)
-> Maybe (HistoryComment () ())
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap \HistoryComment CausalHashId HistoryCommentId
hc -> HistoryComment CausalHashId HistoryCommentId
hc {causal = (), commentId = ()}