{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}

{-# OPTIONS_GHC -fno-warn-name-shadowing
                -fno-warn-unused-binds
                -fno-warn-orphans #-}

module Git.Sample
       ( SampleRepository(..), Repository(..)
       , Git.Oid, BlobOid(), TreeOid(), CommitOid()
       , Tree(), Commit()
       , sampleFactory
       , sampleGet
       ) where

import           Control.Applicative
import           Control.Monad.IO.Class
import           Control.Monad.Trans.Class
import           Control.Monad.Trans.Reader
import           Filesystem.Path.CurrentOS as F
import           Prelude hiding (FilePath)
import qualified Git

data Void
data VoidP p

instance Show Void where
    show _ = undefined

instance Ord Void where
    _ `compare` _ = undefined

instance Eq Void where
    _ == _ = undefined

instance Git.IsOid Void where
    renderOid _ = undefined

instance Git.MonadGit m => Git.Repository (SampleRepository m) where
    type Oid (SampleRepository m)         = Void
    data Tree (SampleRepository m)        = Void
    data Options (SampleRepository m)     = Options

    facts = return Git.RepositoryFacts
        { Git.hasSymbolicReferences = True }

    parseOid          = undefined
    lookupReference   = undefined
    createReference   = undefined
    updateReference   = undefined
    deleteReference   = undefined
    listReferences    = undefined
    lookupCommit      = undefined
    lookupTree        = undefined
    lookupBlob        = undefined
    lookupTag         = undefined
    lookupObject      = undefined
    existsObject      = undefined
    pushCommit        = undefined
    listObjects       = undefined
    newTreeBuilder    = undefined
    treeOid           = undefined
    treeEntry         = undefined
    listTreeEntries   = undefined
    hashContents      = undefined
    createBlob        = undefined
    createCommit      = undefined
    createTag         = undefined
    deleteRepository  = undefined
    remoteFetch       = undefined

-- type TreeEntry m = Git.TreeEntry (SampleRepository m)

data Repository = Repository Void

instance Eq Repository where
  _x == _y = undefined

instance Show Repository where
  show _x = undefined

newtype SampleRepository m a = SampleRepository
    { sampleRepositoryReaderT :: ReaderT Repository m a }
    deriving (Functor, Applicative, Monad, MonadIO, MonadTrans)

type BlobOid m   = Git.BlobOid (SampleRepository m)
type TreeOid m   = Git.TreeOid (SampleRepository m)
type CommitOid m = Git.CommitOid (SampleRepository m)
type TagOid m    = Git.TagOid (SampleRepository m)

type Tree m      = Git.Tree (SampleRepository m)
type Commit m    = Git.Commit (SampleRepository m)
type RefTarget m = Git.RefTarget (SampleRepository m)

sampleGet :: Monad m => SampleRepository m Repository
sampleGet = SampleRepository ask

sampleFactory :: Git.MonadGit m
              => Git.RepositoryFactory SampleRepository m Repository
sampleFactory = Git.RepositoryFactory
    { Git.openRepository  = openSampleRepository
    , Git.runRepository   = runSampleRepository
    , Git.closeRepository = closeSampleRepository
    , Git.getRepository   = sampleGet
    , Git.defaultOptions  = defaultSampleOptions
    , Git.startupBackend  = return ()
    , Git.shutdownBackend = return ()
    }

openSampleRepository :: Git.MonadGit m => Git.RepositoryOptions -> m Repository
openSampleRepository _opts = undefined

runSampleRepository :: Git.MonadGit m
                    => Repository -> SampleRepository m a -> m a
runSampleRepository repo action =
    runReaderT (sampleRepositoryReaderT action) repo

closeSampleRepository :: Git.MonadGit m => Repository -> m ()
closeSampleRepository = const (return ())

defaultSampleOptions :: Git.RepositoryOptions
defaultSampleOptions = Git.RepositoryOptions F.empty False False

-- Sample.hs