content: {-# LANGUAGE OverloadedStrings #-}
  {-# LANGUAGE DeriveGeneric #-}
  module Codec.Xlsx.Types.Internal.CustomProperties where
  
  import Data.Map (Map)
  import qualified Data.Map as M
  import Data.Text (Text)
  import GHC.Generics (Generic)
  import Text.XML
  import Text.XML.Cursor
  
  import Codec.Xlsx.Parser.Internal
  import Codec.Xlsx.Types.Variant
  import Codec.Xlsx.Writer.Internal
  
  newtype CustomProperties = CustomProperties (Map Text Variant)
      deriving (Eq, Show, Generic)
  
  fromList :: [(Text, Variant)] -> CustomProperties
  fromList = CustomProperties . M.fromList
  
  empty :: CustomProperties
  empty = CustomProperties M.empty
  
  {-------------------------------------------------------------------------------
    Parsing
  -------------------------------------------------------------------------------}
  
  instance FromCursor CustomProperties where
    fromCursor cur = do
      let items = cur $/ element (cpr"property") >=> parseCustomPropertyEntry
      return (fromList items)
  
  parseCustomPropertyEntry :: Cursor -> [(Text, Variant)]
  parseCustomPropertyEntry cur = do
    name <- attribute "name" cur
    value <- cur $/ anyElement >=> fromCursor
    return (name, value)
  
  -- | Add custom properties namespace to name
  cpr :: Text -> Name
  cpr x = Name
    { nameLocalName = x
    , nameNamespace = Just custPropNs
    , namePrefix = Nothing
    }
  
  custPropNs :: Text
  custPropNs = "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties"
  
  {-------------------------------------------------------------------------------
    Rendering
  -------------------------------------------------------------------------------}
  
  instance ToDocument CustomProperties where
      toDocument =
          documentFromNsElement "Custom properties generated by xlsx"
          "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties"
          . toElement "Properties"
  
  instance ToElement CustomProperties where
      toElement nm (CustomProperties m) = Element
          { elementName       = nm
          , elementAttributes = M.empty
          , elementNodes      = map (NodeElement . toElement "property" . CustomProperty)
                                . zip [2..] $ M.toList m
          }
  
  newtype CustomProperty = CustomProperty (Int, (Text, Variant))
  
  instance ToElement CustomProperty where
      toElement nm (CustomProperty (i, (key, val))) = Element
          { elementName       = nm
          , elementAttributes = M.fromList [ "name"  .= key
                                           , "fmtid" .= userDefinedFmtID
                                           , "pid"   .= txti i ]
          , elementNodes      = [ NodeElement $ variantToElement val ]
          }
  
  -- | FMTID_UserDefinedProperties
  userDefinedFmtID :: Text
  userDefinedFmtID = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"
  