-- | The @podman@ library provides a simple interface for interacting with a podman API.
-- Use this library to validate the API and integrate podman in Haskell applications.
--
-- This tutorial introduces how to use the @podman@ library to write Haskell scripts.
--
-- In another terminal, ensure the API is running:
--
-- > $ podman --log-level=debug system service --time=0 /var/run/podman.sock
module Podman.Tutorial
  ( -- * Introduction
    -- $intro

    -- * Create the client
    -- $client

    -- * Call endpoint
    -- $request

    -- * Copy files
    -- $files

    -- * Use interactive session
    -- $callback
  )
where

-- $intro
--   To start using this library you need a haskell toolchain, on fedora run:
--
--   > $ sudo dnf install -y ghc cabal-install && cabal update
--
--   Then get a copy of the library by running:
--
--   > $ git clone https://github.com/softwarefactory-project/podman-haskell
--   > $ cd podman-haskell
--
--   Install the library by running:
--
--   > $ cabal install --lib podman
--
--   Validate the library is correctly installed by running:
--
--   > $ ghci
--   > Prelude> import Podman
--   > Prelude Podman> :set prompt "> "
--   > > :set -XOverloadedStrings
--   > > withClient "http+unix://var/run/podman.sock" getVersion
--   > Right (Version {_versionApiVersion = "1.40", _versionVersion = "3.1.0-dev"})

-- $client
--   Most functions require an existing 'Podman.PodmanClient' which carries the
--   endpoint url and the http client manager.
--
--   The only way to get the client is through the 'Podman.withClient' function, which
--   uses a callback function. To make this easier to use in ghci, create this
--   helper:
--
--   > > let c = withClient "http+unix://var/run/podman.sock"
--   > > c $ \client -> getVersion client

-- $request
--   API functions operate with Haskell record, e.g.: 'Podman.Types.InspectContainerResponse'.
--   Each field is a function that can be used with the record:
--
--   > > :type _inspectContainerResponseImageName
--   > _inspectContainerResponseImageName :: InspectContainerResponse -> Text
--
--   For example, to inspect a container named "podman-demo", use 'Podman.containerInspect':
--
--   > > Right res <- c $ \client -> containerInspect client (ContainerName "podman-demo") False
--   > > :t res
--   > res :: InspectContainerResponse
--   > > _inspectContainerResponseImageName res
--   > "registry.access.redhat.com/ubi8/ubi"
--
--   When an API endpoint has complex arguments, the library function also use records:
--
--   * When all the fields are optional, the library provides a default record, e.g. 'Podman.Types.defaultContainerListQuery'.
--   * When some fields are required, the library provides a smart constructor, e.g. 'Podman.Types.mkSpecGenerator'.
--
--   Then the default fields can be modified using the record update syntax:
--
--   > > let myListQuery = defaultContainerListQuery { _containerListQueryall = Just True }
--   > > c $ \client -> containerList client myListQuery
--   > Right [ListContainer {...}, ...]
--
--   The field name can be used in a mapping function, for example, to get the name of
--   all the containers:
--
--   > > (fmap . fmap . fmap $ _listContainerNames) <$> c $ \client -> containerList client myListQuery
--   > Right ["podman-demo", "rootless-cni-infra", "..."]
--
--   Note that we use multiple 'fmap' to penetrate each layer, e.g. MonadIO, Result, and List.

-- $files
--   The send and get files expect @tar@ files, so first import the library and define a utility function:
--
--   > > import qualified Codec.Archive.Tar as Tar
--   > > import qualified Codec.Archive.Tar.Entry as Tar
--   > > let tar = mapM (\(path, content) -> Tar.fileEntry <$> Tar.toTarPath False path <*> pure content)
--
--   Send files with 'Podman.containerSendFiles':
--
--   > > let Right tarball = tar [("test.dat", "test-content")]
--   > > c $ \client -> containerSendFiles client (ContainerName "demo-haskell") tarball "/tmp/test" Nothing
--
--   Get files with 'Podman.containerGetFiles':
--
--   > > c $ \client -> containerGetFiles client (ContainerName "demo-haskell") "/tmp/test"
--   > Right (Next (Entry {entryTarPath = "test", entryContent = Directory, ..}))

-- $callback
--   The interactive functions expect a callback, for example, to get a container log with 'Podman.containerLogs':
--
--   > > c $ \client -> containerLogs client (ContainerName "demo-haskell") LogBoth (defaultLogsQuery {_logsQueryfollow = Just follow}) print
--   > Stdout "container output"
--   > Stdout "..."
--
--   The 'Podman.containerAttach' function provides a 'Podman.ContainerConnection' handler that can be used to read and write.
--   Checkout the podman-demo script for more detailed examples.