{-# LANGUAGE OverloadedStrings #-}
module Network.URI.TLD where

import qualified Data.Set as Set
import Data.Text (Text)
import qualified Data.Text as Text
import qualified Network.URI as URI

import Network.URI.TLD.Internal

-- | Parse a `URI`, and separate the subdomain, domain, and TLD of a URI. 
parseTLDURI :: URI.URI -> Maybe (Text, Text, Text)
parseTLDURI uri = 
    case URI.uriAuthority uri of
        Nothing ->
            Nothing
        Just uriAuth ->
            separateTLD' $ Text.pack $ URI.uriRegName uriAuth

-- | Parse a `String` URI, and separate the subdomain, domain, and TLD.
parseTLD :: String -> Maybe (Text, Text, Text)
parseTLD s = case URI.parseURI s of 
    Nothing ->
        Nothing
    Just uri ->
        parseTLDURI uri

-- | Parse a `Text` URI, and separate the subdomain, domain, and TLD.
parseTLDText :: Text -> Maybe (Text, Text, Text)
parseTLDText = parseTLD . Text.unpack

{-# DEPRECATED separateTLD "Use `parseTLDURI` instead." #-}
separateTLD :: URI.URI -> Maybe (Text, Text, Text)
separateTLD = parseTLDURI

-- | Separate the subdomain, domain, and TLD of a @Text@ string. You probably want to use `parseTLDText`. 
separateTLD' :: Text -> Maybe (Text, Text, Text)
separateTLD' domain = helper "" "" $ Text.toLower domain
    where
        helper _ _ "" = Nothing
        helper subdomain domain tld = 
            if Set.member tld tldSet then
                Just (subdomain, domain, tld)
            else
                let subdomain' = 
                      if Text.null subdomain then
                        domain
                      else
                        Text.concat [subdomain, ".", domain] 
                in
                let (domain', tld') = Text.break (== '.') tld in
                if Text.null domain' then
                    Nothing
                else
                    let (head, tld'') = Text.splitAt 1 tld' in
                    if head /= "." then
                        Nothing
                    else
                        helper subdomain' domain' tld''