content: {-# LANGUAGE FlexibleInstances #-}
  {-# LANGUAGE MultiParamTypeClasses #-}
  {-# LANGUAGE ScopedTypeVariables #-}
  {-# LANGUAGE TypeApplications #-}
  
  module CabalGild.Unstable.Type.Set where
  
  import qualified CabalGild.Unstable.Extra.List as List
  import qualified Data.Proxy as Proxy
  import qualified Data.Set as Set
  import qualified Distribution.CabalSpecVersion as CabalSpecVersion
  import qualified Distribution.Compat.Newtype as Newtype
  import qualified Distribution.FieldGrammar.Newtypes as Newtypes
  import qualified Distribution.Parsec as Parsec
  import qualified Distribution.Pretty as Pretty
  import qualified Text.PrettyPrint as PrettyPrint
  
  -- | A thin wrapper around 'Newtypes.Set''. This is used to define custom
  -- instances of 'Pretty.Pretty' that use trailing commas when the Cabal spec
  -- version is recent enough (at least @2.2@).
  newtype Set s b a = Set
    { unwrap :: Newtypes.Set' s b a
    }
  
  instance Newtype.Newtype (Set.Set a) (Set s b a) where
    pack = Set . Newtype.pack
    unpack = Newtype.unpack . unwrap
  
  instance
    ( Newtype.Newtype a b,
      Ord a,
      Parsec.Parsec b,
      Newtypes.Sep s
    ) =>
    Parsec.Parsec (Set s b a)
    where
    parsec = Set <$> Parsec.parsec
  
  instance
    ( Newtype.Newtype a b,
      Pretty.Pretty b,
      Newtypes.Sep s
    ) =>
    Pretty.Pretty (Set s b a)
    where
    pretty = Pretty.prettyVersioned CabalSpecVersion.CabalSpecV1_0
    prettyVersioned v =
      Newtypes.prettySep (Proxy.Proxy @s)
        . fmap (Pretty.prettyVersioned @b v . Newtype.pack)
        . Set.toAscList
        . Newtype.unpack
  
  -- | Overlaps the more general instance in order to use trailing commas when
  -- possible.
  instance
    {-# OVERLAPPING #-}
    ( Newtype.Newtype a b,
      Pretty.Pretty b
    ) =>
    Pretty.Pretty (Set Newtypes.CommaFSep b a)
    where
    pretty = Pretty.prettyVersioned CabalSpecVersion.CabalSpecV1_0
    prettyVersioned v =
      ( \xs ->
          if List.compareLength xs 1 == GT && v >= CabalSpecVersion.CabalSpecV2_2
            then PrettyPrint.fsep $ fmap (<> PrettyPrint.comma) xs
            else Newtypes.prettySep (Proxy.Proxy @Newtypes.CommaFSep) xs
      )
        . fmap (Pretty.prettyVersioned @b v . Newtype.pack)
        . Set.toAscList
        . Newtype.unpack
  
  -- | Overlaps the more general instance in order to use trailing commas when
  -- possible.
  instance
    {-# OVERLAPPING #-}
    ( Newtype.Newtype a b,
      Pretty.Pretty b
    ) =>
    Pretty.Pretty (Set Newtypes.CommaVCat b a)
    where
    pretty = Pretty.prettyVersioned CabalSpecVersion.CabalSpecV1_0
    prettyVersioned v =
      ( \xs ->
          if List.compareLength xs 1 == GT && v >= CabalSpecVersion.CabalSpecV2_2
            then PrettyPrint.vcat $ fmap (<> PrettyPrint.comma) xs
            else Newtypes.prettySep (Proxy.Proxy @Newtypes.CommaVCat) xs
      )
        . fmap (Pretty.prettyVersioned @b v . Newtype.pack)
        . Set.toAscList
        . Newtype.unpack
  