{-# LANGUAGE Haskell2010 #-}
{-# OPTIONS -Wall #-}

-- | Functions for generating glue code between Haskell and Java.
module Foreign.Java.Bindings (

    -- * Create Haskell glue code from Java definitions
    printJavaPackageModule,
    printJavaClassModule,
    printJavaClassBootfile,
    printJavaClassModule',
    printJavaClassBootfile',

    -- * Reflect Java classes
    reflectJavaClasses,
    findJavaClasses,

    -- ** A priori known information about Java
    javaClassesSE6

  ) where

import Foreign.Java
import Foreign.Java.Utils
import qualified Foreign.Java.Bindings.JavaSE6

import Foreign.Java.Bindings.JavaTypes
import qualified Foreign.Java.Bindings.Java2Haskell as Java2Haskell
import qualified Foreign.Java.Bindings.ReflectJava  as ReflectJava

import Foreign.Java.Bindings.HaskellTypes
import qualified Foreign.Java.Bindings.Haskell2Java   as Haskell2Java
import qualified Foreign.Java.Bindings.ReflectHaskell as ReflectHaskell

import Data.Word

import Data.Map (Map)
import qualified Data.List as List
import qualified Data.Map  as Map


javaClassesSE6 :: [String]
-- ^ The names of all Java Classes part of Java SE 6.
javaClassesSE6 = Foreign.Java.Bindings.JavaSE6.javaClassesSE6

imports :: String
-- ^ Imports of all auto generated java code files.
imports  = ((\_ -> let { __ = 
{-# LINE 48 "Foreign/Java/Bindings.hss" #-}
concat ["import qualified Foreign.Java as JNI\nimport Foreign.Java ((-->))\nimport qualified Prelude as Prelude\nimport Prelude ((.), ($), (>>=), (>>), return)\nimport qualified Foreign.Java.Bindings.Support as JNIS\nimport Data.Functor ((<$>))\n"]
{-# LINE 55 "Foreign/Java/Bindings.hss" #-}
} in __) undefined)

classInfoSignature :: String
-- ^ 
classInfoSignature = "Prelude.String"

classInfo' :: JavaClass -> String
-- ^ 
classInfo' clazz = className clazz

packageInfo' packageName classes = packageName

printJavaPackageModule :: String      -- The Java package name
                       -> String      -- The Haskell module name of the Java package
                       -> Map String JavaClass -- Info about all other classes
                       -> [JavaClass] -- The Java classes contained in the Java package
                       -> String
-- ^ 
printJavaPackageModule packageName modName classInfo classes = ((\_ -> let { __ = 
{-# LINE 73 "Foreign/Java/Bindings.hss" #-}
concat ["{-# LANGUAGE Haskell2010 #-}\n-- | Package @", (packageName), "@\nmodule ", (modName), " (\n", (moduleExports), "    info'\n) where\n", (imports), "\n", (moduleImports), "\n-- Information about this package.\ninfo' = ", (show $ packageInfo' packageName classes), "\n", (moduleDeclarations), "\n"]
{-# LINE 85 "Foreign/Java/Bindings.hss" #-}
} in __) undefined)
  where moduleDeclarations   = Java2Haskell.pkgModDecl     classInfo classes
        moduleImports        = Java2Haskell.pkgModImports  classInfo classes
        moduleExports        = Java2Haskell.pkgModExports  classInfo classes


printJavaClassModule :: JavaClass -- The Java class
                     -> String    -- The Haskell module name of the Java class
                     -> Map String JavaClass -- Info about all classes
                     -> String
-- ^ 
printJavaClassModule clazz modName classInfo = ((\_ -> let { __ = 
{-# LINE 96 "Foreign/Java/Bindings.hss" #-}
concat ["{-# LANGUAGE Haskell2010 #-}\n-- | ", (show $ classType clazz), " @", (classFullName clazz), "@\nmodule ", (modName), " (\n", (moduleExports), "    -- * Information about this class.\n    info'\n) where\n", (imports), "\n", (bootfileImports), "\n", (moduleImports), "\ninfo' = ", (show $ classInfo' clazz), "\n", (bootfileDeclarations), "\n", (moduleDeclarations), "\n"]
{-# LINE 110 "Foreign/Java/Bindings.hss" #-}
} in __) undefined)
  where bootfileDeclarations = Java2Haskell.classBootDecl    classInfo clazz
        bootfileImports      = Java2Haskell.classBootImports classInfo clazz
        moduleDeclarations   = Java2Haskell.classModDecl     classInfo clazz
        moduleImports        = Java2Haskell.classModImports  classInfo clazz
        moduleExports        = Java2Haskell.classModExports  classInfo clazz


printJavaClassBootfile :: JavaClass -- The Java class
                       -> String    -- The Haskell module name of the Java class
                       -> Map String JavaClass -- Info about all classes
                       -> String
-- ^ 
printJavaClassBootfile clazz modName classInfo = ((\_ -> let { __ = 
{-# LINE 123 "Foreign/Java/Bindings.hss" #-}
concat ["{-# LANGUAGE Haskell2010 #-}\n-- Bootfile for class ", (className clazz), "\nmodule ", (modName), " (\n", (bootfileExports), "    info'\n) where\n", (imports), "\n", (bootfileImports), "\ninfo' :: ", (classInfoSignature), "\n", (bootfileDeclarations), "\n"]
{-# LINE 134 "Foreign/Java/Bindings.hss" #-}
} in __) undefined)
  where bootfileDeclarations = Java2Haskell.classBootDecl    classInfo clazz
        bootfileImports      = Java2Haskell.classBootImports classInfo clazz
        bootfileExports      = Java2Haskell.classBootExports classInfo clazz


printJavaClassModule' :: JavaClass -- The Java class
                      -> String    -- The Haskell module name of the Java class
                      -> Map String JavaClass -- Info about all classes
                      -> String
-- ^ 
printJavaClassModule' clazz modName classInfo = ((\_ -> let { __ = 
{-# LINE 145 "Foreign/Java/Bindings.hss" #-}
concat ["{-# LANGUAGE Haskell2010, TypeFamilies #-}\n-- hidden @", (className clazz), "@\nmodule ", (modName), "__ (\n", (moduleExports), "    info'\n) where\n", (imports), "\n", (bootfileImports), "\n", (moduleImports), "\ninfo' = ", (show $ classInfo' clazz), "\n", (bootfileDeclarations), "\n", (moduleDeclarations), "\n"]
{-# LINE 158 "Foreign/Java/Bindings.hss" #-}
} in __) undefined)
  where bootfileDeclarations = Java2Haskell.classBootDecl'    classInfo clazz
        bootfileImports      = Java2Haskell.classBootImports' classInfo clazz
        moduleDeclarations   = Java2Haskell.classModDecl'     classInfo clazz
        moduleImports        = Java2Haskell.classModImports'  classInfo clazz
        moduleExports        = Java2Haskell.classModExports'  classInfo clazz


printJavaClassBootfile' :: JavaClass -- The Java class
                        -> String    -- The Haskell module name of the Java class
                        -> Map String JavaClass -- Info about all classes
                        -> String
-- ^ 
printJavaClassBootfile' clazz modName classInfo = ((\_ -> let { __ = 
{-# LINE 171 "Foreign/Java/Bindings.hss" #-}
concat ["{-# LANGUAGE Haskell2010 #-}\n-- hidden Bootfile for class ", (className clazz), "\nmodule ", (modName), "__ (\n", (bootfileExports), "    info'\n) where\n", (imports), "\n", (bootfileImports), "\ninfo' :: ", (classInfoSignature), "\n", (bootfileDeclarations), "\n"]
{-# LINE 182 "Foreign/Java/Bindings.hss" #-}
} in __) undefined)
  where bootfileDeclarations = Java2Haskell.classBootDecl'    classInfo clazz
        bootfileImports      = Java2Haskell.classBootImports' classInfo clazz
        bootfileExports      = Java2Haskell.classBootExports' classInfo clazz


reflectJavaClasses :: [String]
                   -> Java [JavaClass]
-- ^ Retrieve information about the given Java classes
-- from the Java Virtual Machine.
reflectJavaClasses = ReflectJava.reflectClasses


findJavaClasses :: Word32 -- Maximum depth for following dependencies.
                -> [String]
                -> Java [String]
-- ^ Find all classes that the given classes depend on.
--
-- In order to provide proper bindings for a class, bindings
-- for all classes which a class depends on need to exist too.
-- A class depends on all classes which it inherits from or
-- which are used as arguments, return types, or parameters.
--
-- This functions returns all the class names of the classes
-- on which the given classes depend on. No duplicates are
-- reported and the resulting list is sorted.
findJavaClasses = ReflectJava.findClasses