%  Copyright (C) 2006 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.HopefullyPrivate ( -- ratify HopefullyPrivate: obvously we need it here...
                          Hopefully(..), conscientiously, hopefully,
                          hopefully2either, extractHash,
                          actually, actuallyHashed, unavailable ) where

import Control.Monad ( liftM )
import Printer ( Doc, errorDoc, text, ($$) )
import Darcs.Patch.Info ( PatchInfo, human_friendly )
import Darcs.Patch ( Patch )

data Hopefully a = Actually a | ActuallyHashed String a | Unavailable String

instance Monad Hopefully where
    return a = Actually a
    (Unavailable e) >>= _ = Unavailable e
    (Actually a) >>= f = f a
    (ActuallyHashed _ a) >>= f = f a
    fail e = Unavailable e

instance Functor Hopefully where
    fmap = liftM

hopefully :: (PatchInfo, Hopefully Patch) -> Patch
hopefully = conscientiously $ \e -> text "failed to read patch:" $$ e

conscientiously :: (Doc -> Doc) -> (PatchInfo, Hopefully Patch) -> Patch
conscientiously er (pinf, hp) =
    case hopefully2either hp of
      Right p -> p
      Left e -> errorDoc $ er (human_friendly pinf $$ text e)

sloppily :: Hopefully Patch -> Patch
sloppily hp = case hopefully2either hp of
                Right p -> p
                Left e -> errorDoc $ text "failed to read patch:" $$ text e

-- Any recommendations for a nice adverb to name the below?
hopefully2either :: Hopefully a -> Either String a
hopefully2either (Actually p) = Right p
hopefully2either (ActuallyHashed _ p) = Right p
hopefully2either (Unavailable e) = Left e

actually :: a -> Hopefully a
actually = Actually

actuallyHashed :: String -> a -> Hopefully a
actuallyHashed = ActuallyHashed

extractHash :: Hopefully Patch -> Either Patch String
extractHash (ActuallyHashed s _) = Right s
extractHash hp = Left $ sloppily hp

unavailable :: String -> Hopefully a
unavailable = Unavailable
\end{code}

