-- | IPFS client functions
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE FlexibleContexts #-}

module Blockfrost.Client.IPFS
  ( ipfsAdd
  , ipfsGateway
  , ipfsGetPin
  , ipfsListPins
  , ipfsListPins'
  , ipfsPin
  , ipfsRemovePin
  ) where

import Blockfrost.API
import Blockfrost.Client.Types
import Blockfrost.Types
import Control.Monad.Except
import Data.ByteString.Lazy (ByteString)
import Data.Text (Text)
import qualified Data.Text
import qualified System.Directory
import qualified System.FilePath

ipfsAdd_ :: MonadBlockfrost m => Project -> (ByteString, Form) -> m IPFSAdd
ipfsAdd_ :: forall (m :: * -> *).
MonadBlockfrost m =>
Project -> (ByteString, Form) -> m IPFSAdd
ipfsAdd_ = forall route.
IPFSAPI route
-> route
   :- (Summary "Add a file or directory to IPFS"
       :> (Description
             "You need to `/ipfs/pin/add` an object to avoid it being garbage collected. This usage is being counted in your user account quota."
           :> (Tag "IPFS \187 Add"
               :> ("add" :> (MultipartForm Tmp Form :> Post '[JSON] IPFSAdd)))))
_add forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *).
MonadBlockfrost m =>
Project -> IPFSAPI (AsClientT m)
ipfsClient

-- | Add a file or directory to IPFS
ipfsAdd :: (MonadError BlockfrostError m, MonadBlockfrost m) => FilePath -> m IPFSAdd
ipfsAdd :: forall (m :: * -> *).
(MonadError BlockfrostError m, MonadBlockfrost m) =>
FilePath -> m IPFSAdd
ipfsAdd FilePath
fp = do
  Bool
hasFile <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
System.Directory.doesFileExist FilePath
fp
  if Bool
hasFile
    then do
      forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ FilePath -> IO ()
putStrLn forall a b. (a -> b) -> a -> b
$ FilePath
"Uploading: " forall a. [a] -> [a] -> [a]
++ FilePath
fp
      let fn :: Text
fn = FilePath -> Text
Data.Text.pack forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath
System.FilePath.takeBaseName FilePath
fp
      forall (m :: * -> *) a.
MonadBlockfrost m =>
(Project -> m a) -> m a
go (\Project
proj -> forall (m :: * -> *).
MonadBlockfrost m =>
Project -> (ByteString, Form) -> m IPFSAdd
ipfsAdd_ Project
proj (ByteString
"suchBoundary", (Text -> FilePath -> Form
Form Text
fn FilePath
fp)))
    else
      forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (Text -> BlockfrostError
BlockfrostError Text
"No such file")

ipfsGateway_ :: MonadBlockfrost m => Project -> Text -> m IPFSData
ipfsGateway_ :: forall (m :: * -> *).
MonadBlockfrost m =>
Project -> Text -> m IPFSData
ipfsGateway_ = forall route.
IPFSAPI route
-> route
   :- (Summary "Relay to an IPFS gateway"
       :> (Description
             "Retrieve an object from the IFPS gateway. (Useful if you do not want to rely on a public gateway, such as ``ipfs.blockfrost.dev`)."
           :> (Tag "IPFS \187 Gateway"
               :> ("gateway"
                   :> (Capture "IPFS_path" Text
                       :> Get '[PlainText, OctetStream] IPFSData)))))
_gateway forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *).
MonadBlockfrost m =>
Project -> IPFSAPI (AsClientT m)
ipfsClient

-- | Fetch file via API
ipfsGateway :: MonadBlockfrost m => Text -> m IPFSData
ipfsGateway :: forall (m :: * -> *). MonadBlockfrost m => Text -> m IPFSData
ipfsGateway Text
x = forall (m :: * -> *) a.
MonadBlockfrost m =>
(Project -> m a) -> m a
go (forall (m :: * -> *).
MonadBlockfrost m =>
Project -> Text -> m IPFSData
`ipfsGateway_` Text
x)

ipfsPin_ ::  MonadBlockfrost m => Project -> Text -> m IPFSPinChange
ipfsPin_ :: forall (m :: * -> *).
MonadBlockfrost m =>
Project -> Text -> m IPFSPinChange
ipfsPin_ = forall route.
IPFSAPI route
-> route
   :- (Summary "Pin an object"
       :> (Description
             "Pinned objects are counted in your user storage quota."
           :> (Tag "IPFS \187 Pins"
               :> ("pin"
                   :> ("add"
                       :> (Capture "IPFS_path" Text :> Post '[JSON] IPFSPinChange))))))
_pin forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *).
MonadBlockfrost m =>
Project -> IPFSAPI (AsClientT m)
ipfsClient

-- | Pin an object
ipfsPin :: MonadBlockfrost m => Text -> m IPFSPinChange
ipfsPin :: forall (m :: * -> *). MonadBlockfrost m => Text -> m IPFSPinChange
ipfsPin Text
x = forall (m :: * -> *) a.
MonadBlockfrost m =>
(Project -> m a) -> m a
go (forall (m :: * -> *).
MonadBlockfrost m =>
Project -> Text -> m IPFSPinChange
`ipfsPin_` Text
x)

ipfsListPins_ :: MonadBlockfrost m => Project -> Paged -> SortOrder -> m [IPFSPin]
ipfsListPins_ :: forall (m :: * -> *).
MonadBlockfrost m =>
Project -> Paged -> SortOrder -> m [IPFSPin]
ipfsListPins_ = forall route.
IPFSAPI route
-> route
   :- (Summary "List pinned objects"
       :> (Description "List objects pinned to local storage."
           :> (Tag "IPFS \187 Pins"
               :> ("pin"
                   :> ("list"
                       :> (Pagination :> (Sorting :> Get '[JSON] [IPFSPin])))))))
_listPins forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *).
MonadBlockfrost m =>
Project -> IPFSAPI (AsClientT m)
ipfsClient

-- | List objects pinned to local storage
-- Allows custom paging and ordering using @Paged@ and @SortOrder@.
ipfsListPins' :: MonadBlockfrost m => Paged -> SortOrder -> m [IPFSPin]
ipfsListPins' :: forall (m :: * -> *).
MonadBlockfrost m =>
Paged -> SortOrder -> m [IPFSPin]
ipfsListPins' Paged
pg SortOrder
s = forall (m :: * -> *) a.
MonadBlockfrost m =>
(Project -> m a) -> m a
go (\Project
p -> forall (m :: * -> *).
MonadBlockfrost m =>
Project -> Paged -> SortOrder -> m [IPFSPin]
ipfsListPins_ Project
p Paged
pg SortOrder
s)

-- | List objects pinned to local storage
ipfsListPins :: MonadBlockfrost m => m [IPFSPin]
ipfsListPins :: forall (m :: * -> *). MonadBlockfrost m => m [IPFSPin]
ipfsListPins = forall (m :: * -> *).
MonadBlockfrost m =>
Paged -> SortOrder -> m [IPFSPin]
ipfsListPins' forall a. Default a => a
def forall a. Default a => a
def

ipfsGetPin_ :: MonadBlockfrost m => Project -> Text -> m IPFSPin
ipfsGetPin_ :: forall (m :: * -> *).
MonadBlockfrost m =>
Project -> Text -> m IPFSPin
ipfsGetPin_ = forall route.
IPFSAPI route
-> route
   :- (Summary "Get pinned object details"
       :> (Description "Obtain inormation about specific pinned object."
           :> (Tag "IPFS \187 Pins"
               :> ("pin"
                   :> ("list"
                       :> (Capture "IPFS_path" Text :> Get '[JSON] IPFSPin))))))
_getPin forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *).
MonadBlockfrost m =>
Project -> IPFSAPI (AsClientT m)
ipfsClient

-- | Get pinned object details
ipfsGetPin :: MonadBlockfrost m => Text -> m IPFSPin
ipfsGetPin :: forall (m :: * -> *). MonadBlockfrost m => Text -> m IPFSPin
ipfsGetPin Text
x = forall (m :: * -> *) a.
MonadBlockfrost m =>
(Project -> m a) -> m a
go (forall (m :: * -> *).
MonadBlockfrost m =>
Project -> Text -> m IPFSPin
`ipfsGetPin_` Text
x)

ipfsRemovePin_ :: MonadBlockfrost m => Project -> Text -> m IPFSPinChange
ipfsRemovePin_ :: forall (m :: * -> *).
MonadBlockfrost m =>
Project -> Text -> m IPFSPinChange
ipfsRemovePin_ = forall route.
IPFSAPI route
-> route
   :- (Summary "Remove pinned object from local storage"
       :> (Description "Remove pinned object from local storage"
           :> (Tag "IPFS \187 Pins"
               :> ("pin"
                   :> ("remove"
                       :> (Capture "IPFS_path" Text :> Post '[JSON] IPFSPinChange))))))
_removePin forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *).
MonadBlockfrost m =>
Project -> IPFSAPI (AsClientT m)
ipfsClient

-- | Remove pinned object from local storage
ipfsRemovePin :: MonadBlockfrost m => Text -> m IPFSPinChange
ipfsRemovePin :: forall (m :: * -> *). MonadBlockfrost m => Text -> m IPFSPinChange
ipfsRemovePin Text
x = forall (m :: * -> *) a.
MonadBlockfrost m =>
(Project -> m a) -> m a
go (forall (m :: * -> *).
MonadBlockfrost m =>
Project -> Text -> m IPFSPinChange
`ipfsRemovePin_` Text
x)