{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE Rank2Types #-}

module Descript.Misc.Build.Write.Print.PrintString
  ( pprintStr
  , pprintSummary
  , pprintSummaryRec
  , pprintSummaryRecF
  ) where

import Descript.Misc.Build.Write.Print.Printable
import Descript.Misc.Build.Write.Print.APrint
import Descript.Misc.Ann
import Descript.Misc.Summary
import Data.String
import Data.List

-- | A plain printed string.
newtype PrintString
  = PrintString{ runPrintString :: String }
  deriving (Eq, Monoid, IsString)

instance APrint PrintString where
  plex = PrintString -- Same as 'ppunc'

  pimp = id

  pintercal (PrintString sep)
    = PrintString . intercalate sep . map runPrintString

-- | Pretty-prints the node into a string.
pprintStr :: (Printable a) => a an -> String
pprintStr = runPrintString . aprint

-- | Pretty-prints the node into a string, using the given function to
-- print children.
pprintStrRec :: (Printable a)
             => (forall b. (Printable b) => b an -> String)
             -> a an
             -> String
pprintStrRec sub = runPrintString . aprintRec (PrintString . sub)

-- | Pretty-prints the node into a string, using the given function to
-- print children.
pprintStrRecF :: (FwdPrintable a)
              => (forall b. (Printable b) => b an -> String)
              -> a an
              -> String
pprintStrRecF sub = runPrintString . afprintRec (PrintString . sub)

-- | Gets a summary of the value by printing it. Useful when
-- implementing 'Summary' on leafs ('pprintSummaryRec' for branches):
--
-- > summary = pprintSummary
pprintSummary :: (Printable a) => a an -> String
pprintSummary = pprintStr . remAnns

-- | Gets a summary of the value by printing it. Useful when
-- implementing 'Summary' (on branches or leafs):
--
-- > summaryRec = pprintSummaryRec
pprintSummaryRec :: (Printable a)
                 => (forall b. (Summary b) => b -> String)
                 -> a an
                 -> String
pprintSummaryRec sub = pprintStrRec sub . remAnns

-- | Gets a summary of the value by printing it. Useful when
-- implementing 'Summary' (on branches or leafs):
--
-- > summaryRec = pprintSummaryRec
pprintSummaryRecF :: (FwdPrintable a)
                  => (forall b. (Summary b) => b -> String)
                  -> a an
                  -> String
pprintSummaryRecF sub = pprintStrRecF sub . remAnns