gatherUnsynchronizedEntries :: (RaftLog l e v) => Members -> Configuration -> l -> IO (RaftTime,[RaftLogEntry e])
gatherUnsynchronizedEntries members cfg log = do
    let prevIndex = minimum $ membersAppendedIndex members cfg
        startIndex = prevIndex + 1
    if prevIndex < 0
        then do
            let count = (lastAppended log - startIndex) + 1
            entries <- fetchEntries log startIndex count
            return (initialRaftTime,groupEntries entries)
        else do
            let count = (lastAppended log - prevIndex) + 1
            (prev:rest) <- fetchEntries log prevIndex count
            return (RaftTime (entryTerm prev) prevIndex,groupEntries rest)
    where
        -- we return a list of entries that either has 1 configuration
        -- entry at the beginning (e.g., 'Cfg') and no others, or has no
        -- 'Cfg' entry at all.
        groupEntries [] = []
        groupEntries (first:rest) = if isConfigurationEntry first
            then (first:commandEntries rest)
            else (commandEntries (first:rest))
        isConfigurationEntry = isConfigurationAction . entryAction
        isCommandEntry = isCommandAction . entryAction
        commandEntries = takeWhile isCommandEntry
gatherUnsynchronizedEntries :: (RaftLog l e v) => Members -> Configuration -> l -> IO (RaftTime,[RaftLogEntry e])
gatherUnsynchronizedEntries members cfg log = do
    let prevIndex = minimum $ membersAppendedIndex members cfg
        startIndex = prevIndex + 1
    if prevIndex < 0
        then do
            let count = (lastAppended log - startIndex) + 1
            entries <- fetchEntries log startIndex count
            return (initialRaftTime,groupEntries entries)
        else do
            let count = (lastAppended log - prevIndex) + 1
            (prev:rest) <- fetchEntries log prevIndex count
            return (RaftTime (entryTerm prev) prevIndex,groupEntries rest)
    where
        -- we return a list of entries that either has 1 configuration
        -- entry at the beginning (e.g., 'Cfg') and no others, or has no
        -- 'Cfg' entry at all.
        groupEntries [] = []
        groupEntries (first:rest) = if isConfigurationEntry first
            then (first:commandEntries rest)
            else (commandEntries (first:rest))
        isConfigurationEntry = isConfigurationAction . entryAction
        isCommandEntry = isCommandAction . entryAction
        commandEntries = takeWhile isCommandEntry
gatherUnsynchronizedEntries members cfg log = do
    let prevIndex = minimum $ membersAppendedIndex members cfg
        startIndex = prevIndex + 1
    if prevIndex < 0
        then do
            let count = (lastAppended log - startIndex) + 1
            entries <- fetchEntries log startIndex count
            return (initialRaftTime,groupEntries entries)
        else do
            let count = (lastAppended log - prevIndex) + 1
            (prev:rest) <- fetchEntries log prevIndex count
            return (RaftTime (entryTerm prev) prevIndex,groupEntries rest)
    where
        -- we return a list of entries that either has 1 configuration
        -- entry at the beginning (e.g., 'Cfg') and no others, or has no
        -- 'Cfg' entry at all.
        groupEntries [] = []
        groupEntries (first:rest) = if isConfigurationEntry first
            then (first:commandEntries rest)
            else (commandEntries (first:rest))
        isConfigurationEntry = isConfigurationAction . entryAction
        isCommandEntry = isCommandAction . entryAction
        commandEntries = takeWhile isCommandEntry