content: -- Copyright (c) Microsoft. All rights reserved.
  -- Licensed under the MIT license. See LICENSE file in the project root for full license information.
  
  {-# LANGUAGE OverloadedStrings, RecordWildCards #-}
  
  module Language.Bond.Syntax.Internal
      ( showPretty
      , showQualifiedName
      , takeName
      , takeNamespace
      , isBaseField
      , metaField
      , baseFields
      ) where
  
  import Data.Monoid
  import Language.Bond.Util
  import Language.Bond.Syntax.Util
  import Language.Bond.Syntax.Types
  
  takeName :: QualifiedName -> String
  takeName = last
  
  takeNamespace :: QualifiedName -> QualifiedName
  takeNamespace = subtract 1 . length >>= take
  
  showQualifiedName :: QualifiedName -> String
  showQualifiedName = sepBy "." id
  
  showTypeParams :: [TypeParam] -> String
  showTypeParams = angles . sepBy ", " showPretty
  
  class ShowPretty a where
      showPretty :: a -> String
  
  instance ShowPretty Constraint where
      showPretty Value = ": value"
  
  instance ShowPretty TypeParam where
      showPretty TypeParam {..} = paramName ++ optional showPretty paramConstraint
  
  instance ShowPretty Declaration where
      showPretty Struct {..} = "struct " ++ declName ++ showTypeParams declParams
      showPretty Enum {..} = "enum " ++ declName
      showPretty Forward {..} = "struct declaration " ++ declName ++ showTypeParams declParams
      showPretty Alias {..} = "alias " ++ declName ++ showTypeParams declParams
      showPretty Service {..} = "service " ++ declName ++ showTypeParams declParams
  
  metaField :: Field -> Any
  metaField Field {..} = Any $ isMetaName fieldType
  
  isBaseField :: String -> Maybe Type -> Bool
  isBaseField name = getAny . optional (foldMapFields (Any.(name==).fieldName))
  
  -- If a Declaration is a Struct then return the Fields of its Parent
  baseFields :: Declaration -> Maybe [Field]
  baseFields Struct{..} = foldMapFields return <$> structBase
  baseFields _ = Nothing
  