%  Copyright (C) 2002-2005,2007 David Roundy
%
%  This program is free software; you can redistribute it and/or modify
%  it under the terms of the GNU General Public License as published by
%  the Free Software Foundation; either version 2, 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 General Public License for more details.
%
%  You should have received a copy of the GNU General Public License
%  along with this program; see the file COPYING.  If not, write to
%  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
%  Boston, MA 02110-1301, USA.

\begin{code}
module Darcs.Repository.ApplyPatches ( apply_patches_with_feedback,
                                       apply_patches, simple_feedback
                                     ) where

import System.IO ( hFlush, stdout )
import Control.Monad ( when )

import Darcs.Patch ( Patch, apply )
import Darcs.Hopefully ( Hopefully, hopefully )
import Darcs.Patch.Info ( PatchInfo, human_friendly )
import Darcs.Flags ( DarcsFlag(Verbose, Quiet) )
import Printer ( text, (<+>), (<>), putDocLn, putDoc, Doc )

apply_patches_with_feedback :: [DarcsFlag]
                            ->(Int -> Int -> PatchInfo -> IO())
                            -> (Doc -> IO ())
                            -> [(PatchInfo, Hopefully Patch)] -> IO ()
apply_patches_with_feedback _ _ _ [] = return ()
apply_patches_with_feedback opts feedback putInfo patches = do
    apply_cautiously patches 1
    where patch_count = length patches
          apply_cautiously (hp@(pinfo, _) : more_patches) index =
             do feedback index patch_count pinfo
                apply opts (hopefully hp) `catch` \e ->
                  do putInfo $ text "Unapplicable patch:"
                     putInfo $ human_friendly pinfo
                     ioError e
                apply_cautiously more_patches (index+1)
          apply_cautiously [] _ = return ()

apply_patches :: [DarcsFlag]
              -> (Doc -> IO ()) -> (Doc -> IO ())
              -> [(PatchInfo, Hopefully Patch)] -> IO ()
apply_patches opts putVerbose putInfo patches =
    apply_patches_with_feedback opts normalFeedback putInfo patches
    where normalFeedback _ _ pinfo = putVerbose $ text "Applying patch" <+> human_friendly pinfo  

simple_feedback :: [DarcsFlag] -> String -> Int -> Int -> PatchInfo -> IO ()
simple_feedback opts what index total pinfo =
    if am_verbose
    then putDocLn $ doing <+> q_patch <+> the index <+> q_of <+> the total
                 <> text ":" <+> human_friendly pinfo
    else when am_informative $ do putDoc $ text "\r" <> doing <+> q_patch
                                        <+> the index <+> q_of <+> the total
                                        <> text "... "
                                  hFlush stdout    
                                  when (index == total) $ putDocLn $ text "done."
    where am_verbose = Verbose `elem` opts
          am_informative = not $ Quiet `elem` opts
          doing    = text what
          q_of     = text "of"
          q_patch  = text "patch"
          the i    = text (show i)

\end{code}
