    -- | Maintainer: 2016 Evan Cofsky <evan@theunixman.com>
    --
    -- Functions defining zfs Properties.

    module Propellor.Property.ZFS.Properties (
            ZFSOS,
            zfsExists,
            zfsSetProperties
    ) where

    import Propellor.Base
    import Data.List (intercalate)
    import qualified Propellor.Property.ZFS.Process as ZP

    -- | OS's that support ZFS
    type ZFSOS = Linux + FreeBSD

    -- | Will ensure that a ZFS volume exists with the specified mount point.
    -- This requires the pool to exist as well, but we don't create pools yet.
    zfsExists :: ZFS -> Property ZFSOS
    zfsExists z = check (not <$> ZP.zfsExists z) create
            `describe` unwords ["Creating", zfsName z]
      where
            (p, a) = ZP.zfsCommand "create" [Nothing] z
            create = cmdProperty p a

    -- | Sets the given properties. Returns True if all were successfully changed, False if not.
    zfsSetProperties :: ZFS -> ZFSProperties -> Property ZFSOS
    zfsSetProperties z setProperties = setall
            `requires` zfsExists z
      where
            spcmd :: String -> String -> (String, [String])
            spcmd p v = ZP.zfsCommand "set" [Just (intercalate "=" [p, v]), Nothing] z

            setprop :: (String, String) -> Property ZFSOS
            setprop (p, v) = check (ZP.zfsExists z) $
                    cmdProperty (fst (spcmd p v)) (snd (spcmd p v))

            setall = combineProperties (unwords ["Setting properties on", zfsName z]) $
                    toProps $ map setprop $ toPropertyList setProperties