-- | Multipart names.
module Text.MultipartNames.MultipartName(
    MultipartName,
    mkMultipartName,
    mkMultipartNameFromWords,
    isLegalSegment,
    toSegments
    ) where

-- import Control.Lens
import Data.CaseInsensitive(CI)
import qualified Data.CaseInsensitive as CI
import Data.Char(isAscii, isLetter)

-- | An opaque type that represents a multipart name.  The initial
-- character of each segment must be a cased letter.  Currently, only
-- ASCII letters are allowed as first characters of segments.
newtype MultipartName = MultipartName [CI String]
    deriving (Eq, Ord, Show)

-- | Returns the segments of the name
toSegments :: MultipartName -> [CI String]
toSegments (MultipartName ss) = ss

-- | Creates a multipart name from its segments.
mkMultipartName :: [String] -> MultipartName
mkMultipartName ss
    | null ss		= error "mkMultipartName []: argument cannot be null"
    | all isLegalSegment ss
	  = MultipartName $ map CI.mk ss
    | otherwise		= error msg
    where
    msg = "mkMultipartName " ++ show ss
			     ++ ": all segments must start with a cased letter"

-- | Creates a multipart name from words.  Equivalent to
-- @mkMultipartName . words@.
mkMultipartNameFromWords :: String -> MultipartName
mkMultipartNameFromWords = mkMultipartName . words

-- | Is this string a legal segment for a 'MultipartName'?
isLegalSegment :: String -> Bool
isLegalSegment seg = case seg of
    [] -> False
    c : _ -> isAscii c && isLetter c