module Data.GI.GIR.XMLUtils
    ( nodeToElement
    , subelements
    , localName
    , lookupAttr
    , GIRXMLNamespace(..)
    , lookupAttrWithNamespace
    , childElemsWithLocalName
    , childElemsWithNSName
    , firstChildWithLocalName
    , getElementContent
    , xmlLocalName
    , xmlNSName
    ) where
import Text.XML (Element(elementNodes, elementName, elementAttributes),
                 Node(NodeContent, NodeElement), nameLocalName, Name(..))
import Data.Maybe (mapMaybe, listToMaybe)
import qualified Data.Map as M
import Data.Text (Text)
nodeToElement :: Node -> Maybe Element
nodeToElement (NodeElement e) = Just e
nodeToElement _               = Nothing
subelements :: Element -> [Element]
subelements = mapMaybe nodeToElement . elementNodes
localName :: Element -> Text
localName = nameLocalName . elementName
childElemsWithLocalName :: Text -> Element -> [Element]
childElemsWithLocalName n =
    filter localNameMatch . subelements
    where localNameMatch = (== n) . localName
childElemsWithNSName :: GIRXMLNamespace -> Text -> Element -> [Element]
childElemsWithNSName ns n = filter nameMatch . subelements
    where nameMatch = (== name) . elementName
          name = Name {
                   nameLocalName = n
                 , nameNamespace = Just (girNamespace ns)
                 , namePrefix = Nothing
                 }
firstChildWithLocalName :: Text -> Element -> Maybe Element
firstChildWithLocalName n = listToMaybe . childElemsWithLocalName n
getElementContent :: Element -> Maybe Text
getElementContent = listToMaybe . mapMaybe getContent . elementNodes
    where getContent :: Node -> Maybe Text
          getContent (NodeContent t) = Just t
          getContent _ = Nothing
lookupAttr :: Name -> Element -> Maybe Text
lookupAttr attr element = M.lookup attr (elementAttributes element)
data GIRXMLNamespace = GLibGIRNS | CGIRNS | CoreGIRNS
                     deriving Show
girNamespace :: GIRXMLNamespace -> Text
girNamespace GLibGIRNS = "http://www.gtk.org/introspection/glib/1.0"
girNamespace CGIRNS = "http://www.gtk.org/introspection/c/1.0"
girNamespace CoreGIRNS = "http://www.gtk.org/introspection/core/1.0"
lookupAttrWithNamespace :: GIRXMLNamespace -> Name -> Element -> Maybe Text
lookupAttrWithNamespace ns attr element =
    let attr' = attr {nameNamespace = Just (girNamespace ns)}
    in M.lookup attr' (elementAttributes element)
xmlLocalName :: Text -> Name
xmlLocalName n = Name { nameLocalName = n
                      , nameNamespace = Nothing
                      , namePrefix = Nothing }
xmlNSName :: GIRXMLNamespace -> Text -> Name
xmlNSName ns n = Name { nameLocalName = n
                      , nameNamespace = Just (girNamespace ns)
                      , namePrefix = Nothing }