module Darcs.Patch.FileHunk
    ( FileHunk(..), IsHunk(..), showFileHunk, showContextFileHunk
    )
    where

import Darcs.Prelude

import Darcs.Patch.Apply ( ObjectIdOfPatch )
import Darcs.Patch.Format ( FileNameFormat )
import Darcs.Patch.Invert ( Invert(..) )
import Darcs.Patch.Object ( ObjectId(..) )

import Darcs.Util.Printer
    ( Doc, blueText, text, lineColor, vcat, userchunkPS
    , prefix, ($$), (<+>), Color(Cyan, Magenta) )

import qualified Data.ByteString as B ( ByteString )


data FileHunk oid wX wY = FileHunk oid !Int [B.ByteString] [B.ByteString]

type role FileHunk nominal nominal nominal

class IsHunk p where
    isHunk :: p wX wY -> Maybe (FileHunk (ObjectIdOfPatch p) wX wY)

showFileHunk :: ObjectId oid => FileNameFormat -> FileHunk oid wX wY -> Doc
showFileHunk :: forall oid wX wY.
ObjectId oid =>
FileNameFormat -> FileHunk oid wX wY -> Doc
showFileHunk FileNameFormat
x (FileHunk oid
f Int
line [ByteString]
old [ByteString]
new) =
           String -> Doc
blueText String
"hunk" Doc -> Doc -> Doc
<+> FileNameFormat -> oid -> Doc
forall oid. ObjectId oid => FileNameFormat -> oid -> Doc
formatObjectId FileNameFormat
x oid
f Doc -> Doc -> Doc
<+> String -> Doc
text (Int -> String
forall a. Show a => a -> String
show Int
line)
        Doc -> Doc -> Doc
$$ Color -> Doc -> Doc
lineColor Color
Magenta (String -> Doc -> Doc
prefix String
"-" ([Doc] -> Doc
vcat ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ (ByteString -> Doc) -> [ByteString] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map ByteString -> Doc
userchunkPS [ByteString]
old))
        Doc -> Doc -> Doc
$$ Color -> Doc -> Doc
lineColor Color
Cyan    (String -> Doc -> Doc
prefix String
"+" ([Doc] -> Doc
vcat ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ (ByteString -> Doc) -> [ByteString] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map ByteString -> Doc
userchunkPS [ByteString]
new))

showContextFileHunk
  :: ObjectId oid
  => FileNameFormat
  -> [B.ByteString]
  -> FileHunk oid wB wC
  -> [B.ByteString]
  -> Doc
showContextFileHunk :: forall oid wB wC.
ObjectId oid =>
FileNameFormat
-> [ByteString] -> FileHunk oid wB wC -> [ByteString] -> Doc
showContextFileHunk FileNameFormat
fmt [ByteString]
pre (FileHunk oid
f Int
l [ByteString]
o [ByteString]
n) [ByteString]
post =
  String -> Doc
blueText String
"hunk" Doc -> Doc -> Doc
<+> FileNameFormat -> oid -> Doc
forall oid. ObjectId oid => FileNameFormat -> oid -> Doc
formatObjectId FileNameFormat
fmt oid
f Doc -> Doc -> Doc
<+> String -> Doc
text (Int -> String
forall a. Show a => a -> String
show Int
l) Doc -> Doc -> Doc
$$
  String -> Doc -> Doc
prefix String
" " ([Doc] -> Doc
vcat ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ (ByteString -> Doc) -> [ByteString] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map ByteString -> Doc
userchunkPS [ByteString]
pre) Doc -> Doc -> Doc
$$
  Color -> Doc -> Doc
lineColor Color
Magenta (String -> Doc -> Doc
prefix String
"-" ([Doc] -> Doc
vcat ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ (ByteString -> Doc) -> [ByteString] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map ByteString -> Doc
userchunkPS [ByteString]
o)) Doc -> Doc -> Doc
$$
  Color -> Doc -> Doc
lineColor Color
Cyan (String -> Doc -> Doc
prefix String
"+" ([Doc] -> Doc
vcat ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ (ByteString -> Doc) -> [ByteString] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map ByteString -> Doc
userchunkPS [ByteString]
n)) Doc -> Doc -> Doc
$$
  String -> Doc -> Doc
prefix String
" " ([Doc] -> Doc
vcat ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ (ByteString -> Doc) -> [ByteString] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map ByteString -> Doc
userchunkPS [ByteString]
post)

instance Invert (FileHunk oid) where
    invert :: forall wX wY. FileHunk oid wX wY -> FileHunk oid wY wX
invert (FileHunk oid
path Int
line [ByteString]
old [ByteString]
new) = oid -> Int -> [ByteString] -> [ByteString] -> FileHunk oid wY wX
forall oid wX wY.
oid -> Int -> [ByteString] -> [ByteString] -> FileHunk oid wX wY
FileHunk oid
path Int
line [ByteString]
new [ByteString]
old