{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE NoImplicitPrelude #-}

module Precursor.Text.Text
  ( fromString
  , IsText(..)
  , IsBytes(..)
  , Text
  , ByteString
  , StrictText
  , StrictByteString
  , singleton
  , fromChunks
  , toChunks
  , toCaseFold
  , toLower
  , toUpper
  , toTitle
  , lines
  , words
  , unlines
  , unwords
  , isPrefixOf
  , isSuffixOf
  , isInfixOf
  ) where


import qualified Data.ByteString               as Strict
import           Data.ByteString.Lazy          (ByteString)
import qualified Data.ByteString.Lazy          as ByteString
import qualified Data.Text                     as Strict
import qualified Data.Text.Encoding            as Strict
import           Data.Text.Encoding.Error
import           Data.Text.Lazy
import           Data.Text.Lazy.Encoding
import           GHC.Exts                      (fromString)
import           Precursor.Control.Applicative
import           Precursor.Control.Category
import           Precursor.Control.Functor
import           Precursor.Data.Either

type StrictText = Strict.Text
type StrictByteString = Strict.ByteString

class IsText a where
  {-# MINIMAL (fromText | fromText'), (readBytes | readBytes') #-}
  fromText   :: Text -> a
  fromText'  :: StrictText -> a
  readBytes' :: StrictByteString -> Either UnicodeException a
  readBytes  :: ByteString -> Either UnicodeException a
  fromText   = fromText'  . toStrict
  fromText'  = fromText   . fromStrict
  readBytes  = readBytes' . ByteString.toStrict
  readBytes' = readBytes  . ByteString.fromStrict

class IsText a => IsBytes a where
  {-# MINIMAL (fromBytes | fromBytes') #-}
  fromBytes  :: ByteString -> a
  fromBytes' :: StrictByteString -> a
  fromBytes  = fromBytes' . ByteString.toStrict
  fromBytes' = fromBytes . ByteString.fromStrict

instance IsText Text where
  fromText   = id
  fromText'  = fromStrict
  readBytes  = decodeUtf8'
  readBytes' = fmap fromStrict . Strict.decodeUtf8'

instance IsText Strict.Text where
  fromText   = toStrict
  fromText'  = id
  readBytes' = Strict.decodeUtf8'
  readBytes  = fmap toStrict  . decodeUtf8'

instance IsText ByteString where
  fromText  = encodeUtf8
  readBytes = pure

instance IsText Strict.ByteString where
  fromText'  = Strict.encodeUtf8
  readBytes' = pure

instance IsBytes ByteString where
  fromBytes = id

instance IsBytes Strict.ByteString where
  fromBytes' = id