-- Copyright (C) 2011 Petr Rockai
--
-- Permission is hereby granted, free of charge, to any person
-- obtaining a copy of this software and associated documentation
-- files (the "Software"), to deal in the Software without
-- restriction, including without limitation the rights to use, copy,
-- modify, merge, publish, distribute, sublicense, and/or sell copies
-- of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be
-- included in all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-- SOFTWARE.

module Darcs.Patch.Prim.FileUUID.ObjectMap
    ( UUID(..), Location(..), Object(..)
    , ObjectMap(..), DirContent, FileContent
    , isBlob, isDirectory
    , Name -- re-export
    ) where

import Darcs.Prelude

import Darcs.Patch.Object ( ObjectIdOf )
import Darcs.Util.Hash ( Hash )
import Darcs.Util.Path ( Name )
import qualified Data.ByteString as B (ByteString)
import qualified Data.Map as M

type FileContent = B.ByteString

newtype UUID = UUID B.ByteString deriving (UUID -> UUID -> Bool
(UUID -> UUID -> Bool) -> (UUID -> UUID -> Bool) -> Eq UUID
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: UUID -> UUID -> Bool
== :: UUID -> UUID -> Bool
$c/= :: UUID -> UUID -> Bool
/= :: UUID -> UUID -> Bool
Eq, Eq UUID
Eq UUID =>
(UUID -> UUID -> Ordering)
-> (UUID -> UUID -> Bool)
-> (UUID -> UUID -> Bool)
-> (UUID -> UUID -> Bool)
-> (UUID -> UUID -> Bool)
-> (UUID -> UUID -> UUID)
-> (UUID -> UUID -> UUID)
-> Ord UUID
UUID -> UUID -> Bool
UUID -> UUID -> Ordering
UUID -> UUID -> UUID
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: UUID -> UUID -> Ordering
compare :: UUID -> UUID -> Ordering
$c< :: UUID -> UUID -> Bool
< :: UUID -> UUID -> Bool
$c<= :: UUID -> UUID -> Bool
<= :: UUID -> UUID -> Bool
$c> :: UUID -> UUID -> Bool
> :: UUID -> UUID -> Bool
$c>= :: UUID -> UUID -> Bool
>= :: UUID -> UUID -> Bool
$cmax :: UUID -> UUID -> UUID
max :: UUID -> UUID -> UUID
$cmin :: UUID -> UUID -> UUID
min :: UUID -> UUID -> UUID
Ord, Int -> UUID -> ShowS
[UUID] -> ShowS
UUID -> String
(Int -> UUID -> ShowS)
-> (UUID -> String) -> ([UUID] -> ShowS) -> Show UUID
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> UUID -> ShowS
showsPrec :: Int -> UUID -> ShowS
$cshow :: UUID -> String
show :: UUID -> String
$cshowList :: [UUID] -> ShowS
showList :: [UUID] -> ShowS
Show)

-- | An object is located by giving the 'UUID' of the parent
-- 'Directory' and a 'Name'.
data Location = L !UUID !Name
  deriving (Location -> Location -> Bool
(Location -> Location -> Bool)
-> (Location -> Location -> Bool) -> Eq Location
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Location -> Location -> Bool
== :: Location -> Location -> Bool
$c/= :: Location -> Location -> Bool
/= :: Location -> Location -> Bool
Eq, Int -> Location -> ShowS
[Location] -> ShowS
Location -> String
(Int -> Location -> ShowS)
-> (Location -> String) -> ([Location] -> ShowS) -> Show Location
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Location -> ShowS
showsPrec :: Int -> Location -> ShowS
$cshow :: Location -> String
show :: Location -> String
$cshowList :: [Location] -> ShowS
showList :: [Location] -> ShowS
Show)

-- TODO use HashMap instead?
type DirContent = M.Map Name UUID

data Object (m :: * -> *)
  = Directory DirContent
  | Blob (m FileContent) !(Maybe Hash)

isBlob :: Object m -> Bool
isBlob :: forall (m :: * -> *). Object m -> Bool
isBlob Blob{} = Bool
True
isBlob Directory{} = Bool
False

isDirectory :: Object m -> Bool
isDirectory :: forall (m :: * -> *). Object m -> Bool
isDirectory Directory{} = Bool
True
isDirectory Blob{} = Bool
False

data ObjectMap (m :: * -> *) = ObjectMap
  { forall (m :: * -> *). ObjectMap m -> UUID -> m (Maybe (Object m))
getObject :: UUID -> m (Maybe (Object m))
  , forall (m :: * -> *).
ObjectMap m -> UUID -> Object m -> m (ObjectMap m)
putObject :: UUID -> Object m -> m (ObjectMap m)
  , forall (m :: * -> *). ObjectMap m -> m [UUID]
listObjects :: m [UUID]
  }

type instance ObjectIdOf ObjectMap = UUID