module Text.Quote (
  Quote (SingleQuote, DoubleQuote)
  , AsQuote (_Quote, _SingleQuote, _DoubleQuote)
  , quoteChar
  , quoteToString
) where
import Control.DeepSeq (NFData (rnf))
import Control.Lens (Prism', prism, prism', review)
import Data.String (IsString (fromString))
data Quote =
    SingleQuote
  | DoubleQuote
  deriving (Eq, Ord, Show)
instance NFData Quote where
  rnf x = seq x ()
class AsQuote r where
  _Quote :: Prism' r Quote
  _SingleQuote :: Prism' r ()
  _DoubleQuote :: Prism' r ()
  _SingleQuote = _Quote . _SingleQuote
  _DoubleQuote = _Quote . _DoubleQuote
instance AsQuote Quote where
  _Quote = id
  _SingleQuote = prism (const SingleQuote) $ \x -> case x of
    SingleQuote -> Right ()
    DoubleQuote -> Left x
  _DoubleQuote = prism (const DoubleQuote) $ \x -> case x of
    SingleQuote -> Left x
    DoubleQuote -> Right ()
instance AsQuote Char where
  _Quote = quoteChar
quoteChar :: Prism' Char Quote
quoteChar =
  prism'
    (\q -> case q of
      SingleQuote -> '\''
      DoubleQuote -> '"')
    (\c -> case c of
      '\'' -> Just SingleQuote
      '"'  -> Just DoubleQuote
      _    -> Nothing)
quoteToString :: IsString a => Quote -> a
quoteToString = fromString . pure . review quoteChar