{-|

  Modules under "Bindings" are supposed to be low level links to
  non-Haskell packages, sharing a set of community driven guidelines on
  procedures, goals and style. (Note that, until others get interested
  in this work, \"community\" means just the author.) This is the
  current set of guidelines:

  * Code should be portable and easy to build.

  * There should be a one-to-one relashionship between names in the
  original library and its bindings. Also, the behavior of elements
  should be what would be expected from the element of the original
  library it represents.

  * As a planed consequence of the former item, the reference
  documentation for all modules should be the documentation available
  for the original libraries. Documentation and comments to Haskell
  binding code should be restricted to explain decisions that had to be
  made to solve ambiguities or provide functionality that could not be
  mapped to an exact Haskell equivalent.

  * All foreign functions are declared @safe@. Also, they should
  all result in a 'System.IO.IO', even when they are supposed to
  be effect-free. This is both for consistency and security, since
  otherwise it would be difficult to inspect all the code to check which
  functions are actually guaranteed to be effect-free. Constant values,
  however, may be represented by pure functions.

  * Global variables whose values can be changed by a library user
  are wrapped throw type 'Bindings.Utilities.GlobalVar'. When their
  values can't be changed by the user, but still they can change as
  the execution goes, they are wrapped throw functions returning an
  'System.IO.IO'. (This last case, of course, may need helper functions
  written in the foreign language.)

  * Names in Haskell should match the corresponding names in original
  libraries, prefixed with \'@_@\' when starting with an uppercase
  letter, or with first letter uppercased when naming types. Exception
  is made to prefixes used to emulate namespaces. In this case, prefixes
  are stripped, and they are expected to be replaced by qualified
  imports, e.g., a function named @somepkg_anyfun@ should be named just
  @anyfun@ and may be used as @SomePkg.anyfun@. Also names for basic
  types, like fixed size integers or pointers, should be consistent with
  style used in "Foreign.C.Types".

  * Module "Bindings.Utilities" has an enumeration of function types
  ('Bindings.Utilities.CB0001', 'Bindings.Utilities.CB0002' etc.) which are
  supposed to be used (and incremented when necessary) to type callback
  functions. Foreign functions parameters expecting callback pointers
  should be typed as pointers to function types in that enumeration;
  except when those callbacks are just data destructors, when they
  should be typed as 'Foreign.ForeignPtr.FinalizerPtr'.

  * Users can suggest tests using "Test.HUnit" or "Test.QuickCheck"
  using the bug tracking system. Test shown to be valid will be included
  with a test program included in this package.

  The names for files and directories in the source pack follow the
  usual convention of mapping module names to file names. A similar
  convention is followed by C files that support those modules. There
  are also a few special directories:

  [@packageCode@] This directory contains the source code for the
  foreign libraries. When appropriate, steps necessary to build a library
  will be listed in a file here.

  [@packageCode\/include@] Support files needed by this package to
  properly wrapp libraries (like @C@ include files) are placed here.
  They should be simplified as much as possible to contain only the
  required information.

  [@traduttoreTraditore@] Here example code for wrapped libraries can be
  found. However, only Haskell translations for code already available
  for those libraries in \"official\" places (like the homepage for the
  library, or inside its source code distribution) are allowed. Best
  effort should be made to keep those translations faithfull to the
  original code, so that readers could follow then side by side.

-}

module Bindings where
import Foreign
import Foreign.C
import Control.Monad
import Control.Exception

data License = ApacheLicenseV2 | BSD3 | GPL | GPLv3 | LGPL | LGPLv3
  | MIT | MPL | CDDL | CPL | EPL | ArtisticLicenseV2 | OSLv3 | Zlib |
  AfferoGNUv3 | SimPLv2 | Proprietary | Private

data Package = Sqlite3 deriving (Eq, Show)

-- | Given the license you have choosen for your
-- work, this function tells you which libraries
-- in this package you're allowed to use.

whatCanBeUsedWithThisLicense :: License -> [Package]
whatCanBeUsedWithThisLicense _ = [Sqlite3]

-- | When libraries require an initialization call to
-- be made at startup, the related functions are not
-- wrapped. Instead, we use 'initialize' as a common
-- initialization point for all libraries. You can
-- use 'initialize' at the beginning of 'main' and
-- 'shutdown' at the end. Repeated calls to 'initialize'
-- cause no harm.

initialize :: [Package] -> IO ()
initialize p = do
  when (Sqlite3 `elem` p) $ do
    status <- bindings_init_sqlite3
    when (status == 0) $ (throwIO $ AssertionFailed "Failed \
        \initialization of libraries in package 'bindings'.") >> return ()

initializeAll = initialize [Sqlite3]
shutdown = bindings_shutdown

foreign import ccall "bindings_init_sqlite3" bindings_init_sqlite3
  :: IO CInt
foreign import ccall "bindings_shutdown" bindings_shutdown
  :: IO ()