content: -- Copyright (c) Microsoft. All rights reserved.
  -- Licensed under the MIT license. See LICENSE file in the project root for full license information.
  
  {-# LANGUAGE QuasiQuotes, OverloadedStrings, RecordWildCards #-}
  
  module Language.Bond.Codegen.Java.Util
      ( qualifiedDeclaredTypeName
      , generatedClassAnnotations
      , modifierConstantName
      , isPrimitiveNonEnumBondType
      , isPrimitiveBondType
      , isGenericBondStructType
      , twosComplement
      ) where
  
  import Prelude
  import Data.List (intercalate)
  import Data.Text.Lazy (Text)
  import Text.Shakespeare.Text
  import Language.Bond.Syntax.Types
  import Language.Bond.Syntax.Util
  import Language.Bond.Codegen.TypeMapping
  import Language.Bond.Codegen.Util()
  
  -- returns the fully qualified name for a declaration
  qualifiedDeclaredTypeName :: MappingContext -> Declaration -> String
  qualifiedDeclaredTypeName java d  = intercalate "." $ getDeclNamespace java d ++ [declName d]
  
  -- returns the Java annotations for a generated class
  generatedClassAnnotations :: Text
  generatedClassAnnotations = [lt|@javax.annotation.Generated("gbc")|]
  
  -- returns the qualified name of Modifier constant
  modifierConstantName :: Modifier -> Text
  modifierConstantName Optional = [lt|org.bondlib.Modifier.Optional|]
  modifierConstantName Required = [lt|org.bondlib.Modifier.Required|]
  modifierConstantName RequiredOptional = [lt|org.bondlib.Modifier.RequiredOptional|]
  
  -- returns a value indicating whether a type is a non-enum Bond primitive type
  isPrimitiveNonEnumBondType :: Type -> Bool
  isPrimitiveNonEnumBondType BT_Int8 = True
  isPrimitiveNonEnumBondType BT_Int16 = True
  isPrimitiveNonEnumBondType BT_Int32 = True
  isPrimitiveNonEnumBondType BT_Int64 = True
  isPrimitiveNonEnumBondType BT_UInt8 = True
  isPrimitiveNonEnumBondType BT_UInt16 = True
  isPrimitiveNonEnumBondType BT_UInt32 = True
  isPrimitiveNonEnumBondType BT_UInt64 = True
  isPrimitiveNonEnumBondType BT_Float = True
  isPrimitiveNonEnumBondType BT_Double = True
  isPrimitiveNonEnumBondType BT_Bool = True
  isPrimitiveNonEnumBondType BT_String = True
  isPrimitiveNonEnumBondType BT_WString = True
  isPrimitiveNonEnumBondType BT_MetaName = True
  isPrimitiveNonEnumBondType BT_MetaFullName = True
  isPrimitiveNonEnumBondType (BT_UserDefined a@Alias {} args) = isPrimitiveNonEnumBondType (resolveAlias a args)
  isPrimitiveNonEnumBondType _ = False
  
  -- returns a value indicating whether a type is a Bond primitive type or enum
  isPrimitiveBondType :: Type -> Bool
  isPrimitiveBondType (BT_UserDefined Enum {..} _) = True
  isPrimitiveBondType t = isPrimitiveNonEnumBondType t
  
  -- returns a value indicating whether a type is a generic struct type with generic type parameters
  isGenericBondStructType :: Type -> Bool
  isGenericBondStructType (BT_UserDefined Struct {..} _) = not (null declParams)
  isGenericBondStructType _ = False
  
  -- takes a bit count and a number and returns its two's complement
  twosComplement :: Integer -> Integer -> Integer
  twosComplement bitCount value = if value < (2 ^ (bitCount - 1))
      then value
      else value - (2 ^ bitCount)
  