applyChangesRemote :: FilePath -> Map Path RemoteFile -> [Change] -> ApiAction [Change]
applyChangesRemote syncDir rState = fmap catMaybes . applyChanges rState
    where
        applyChanges :: Map Path RemoteFile -> [Change] -> ApiAction [Maybe Change]
        applyChanges _ [] = return []
        applyChanges remoteState (headChange:tailChanges) =
                case headChange of
                    Created (Dir createdPath) -> do
                        res <- tryWithLogging $ applyCreatedDirToRemote createdPath
                        let appliedHead = fmap fst res
                        let newFolder = fmap snd res
                        let newState = case newFolder of
                                            Just nf -> Map.insert createdPath nf remoteState
                                            Nothing -> remoteState
                        appliedTail <- applyChanges newState tailChanges
                        return $ appliedHead : appliedTail
                    Created (File createdPath _) -> do
                        res <- tryWithLogging $ applyCreatedFileToRemote syncDir remoteState createdPath
                        let appliedHead = fmap fst res
                        let newFile = fmap snd res
                        let newState = case newFile of
                                            Just nf -> Map.insert createdPath nf remoteState
                                            Nothing -> remoteState
                        appliedTail <- applyChanges newState tailChanges
                        return $ appliedHead : appliedTail
                    Deleted file -> do
                        appliedHead <- tryWithLogging $ applyDeletedToRemote remoteState file
                        appliedTail <- applyChanges remoteState tailChanges
                        return $ appliedHead : appliedTail
applyChangesRemote :: FilePath -> Map Path RemoteFile -> [Change] -> ApiAction [Change]
applyChangesRemote syncDir rState = fmap catMaybes . applyChanges rState
    where
        applyChanges :: Map Path RemoteFile -> [Change] -> ApiAction [Maybe Change]
        applyChanges _ [] = return []
        applyChanges remoteState (headChange:tailChanges) =
                case headChange of
                    Created (Dir createdPath) -> do
                        res <- tryWithLogging $ applyCreatedDirToRemote createdPath
                        let appliedHead = fmap fst res
                        let newFolder = fmap snd res
                        let newState = case newFolder of
                                            Just nf -> Map.insert createdPath nf remoteState
                                            Nothing -> remoteState
                        appliedTail <- applyChanges newState tailChanges
                        return $ appliedHead : appliedTail
                    Created (File createdPath _) -> do
                        res <- tryWithLogging $ applyCreatedFileToRemote syncDir remoteState createdPath
                        let appliedHead = fmap fst res
                        let newFile = fmap snd res
                        let newState = case newFile of
                                            Just nf -> Map.insert createdPath nf remoteState
                                            Nothing -> remoteState
                        appliedTail <- applyChanges newState tailChanges
                        return $ appliedHead : appliedTail
                    Deleted file -> do
                        appliedHead <- tryWithLogging $ applyDeletedToRemote remoteState file
                        appliedTail <- applyChanges remoteState tailChanges
                        return $ appliedHead : appliedTail
applyChangesRemote syncDir rState = fmap catMaybes . applyChanges rState
    where
        applyChanges :: Map Path RemoteFile -> [Change] -> ApiAction [Maybe Change]
        applyChanges _ [] = return []
        applyChanges remoteState (headChange:tailChanges) =
                case headChange of
                    Created (Dir createdPath) -> do
                        res <- tryWithLogging $ applyCreatedDirToRemote createdPath
                        let appliedHead = fmap fst res
                        let newFolder = fmap snd res
                        let newState = case newFolder of
                                            Just nf -> Map.insert createdPath nf remoteState
                                            Nothing -> remoteState
                        appliedTail <- applyChanges newState tailChanges
                        return $ appliedHead : appliedTail
                    Created (File createdPath _) -> do
                        res <- tryWithLogging $ applyCreatedFileToRemote syncDir remoteState createdPath
                        let appliedHead = fmap fst res
                        let newFile = fmap snd res
                        let newState = case newFile of
                                            Just nf -> Map.insert createdPath nf remoteState
                                            Nothing -> remoteState
                        appliedTail <- applyChanges newState tailChanges
                        return $ appliedHead : appliedTail
                    Deleted file -> do
                        appliedHead <- tryWithLogging $ applyDeletedToRemote remoteState file
                        appliedTail <- applyChanges remoteState tailChanges
                        return $ appliedHead : appliedTail