{-- TerraHS - Interface between TerraLib and Haskell

    (c) Sergio Costa (INPE) - Setembro, 2005

	This program is free software; you can redistribute it 
    and/or modify it under the terms of the GNU General 
    Public License 2.1 as published by the Free Software Foundation
    (http://www.opensource.org/licenses/gpl-license.php)
--}

{- |
	A module for supporting a TeDatabase TerraLib class

	Instances of this classes represent connections
	to a database server. It includes the host name, 
	user name and password parameters of the connection.
	It should be implemented by the drivers to specific
	database servers as: MySQL, Ado, PostgreSQL or any
	other server to be used in TerraLib applications.

	 More information - <http://www.terralib.org>
-}
module TerraHS.TerraLib.TeDatabase
	(
	
	-- * The @TeDatabase@ type
	TeDatabase(..),

	-- * The @TeDatabasePtr@ type
	TeDatabasePtr,
	
	-- * The @Layers@ class	
	TeDatabases (..) ,
	
	teimportraster,
	) 
	where


import Foreign.C.String
import qualified Foreign.Ptr (Ptr)

import TerraHS.Misc.Object
import TerraHS.Misc.Generic

import TerraHS.TerraLib.TeGeometry
import TerraHS.TerraLib.TeGeometryAlgorithms
import TerraHS.TerraLib.TeSTInstance
import TerraHS.TerraLib.TeLayer
import TerraHS.TerraLib.TeRaster
import TerraHS.TerraLib.TeTable
import TerraHS.TerraLib.TeQuerier

import TerraHS.Misc.Databases


class TeDatabases a where
	-- | Load information about a particular layer 
	loadLayer :: (Foreign.Ptr.Ptr a) -> String -> Prelude.IO TeLayerPtr
	-- | Gets the last error message
	errorMessage :: (Foreign.Ptr.Ptr a) -> Prelude.IO String
	
	loadRaster:: (Foreign.Ptr.Ptr a) -> String -> IO (TeRaster Double)
	
	importRaster :: (Foreign.Ptr.Ptr a) -> String 	-> (TeRaster Double) -> Prelude.IO Bool
	
	importRasterWParameter :: (Foreign.Ptr.Ptr a) -> String -> Double -> (TeRaster Double) -> Prelude.IO Bool

data TeDatabase = TeMySQL String String String String | TePostgreSQL

-- | The type @TeDatabasePtr@ is a pointer to @TeDatabase@
type TeDatabasePtr = Foreign.Ptr.Ptr TeDatabase

instance Connection TeDatabase where

	open (TeMySQL host user pass dbname) = do
		h <- newCString host 
		u <- newCString user 
		p <- newCString pass 
		n <- newCString dbname 
		ptr <- new (TeMySQL host user pass dbname)
		st <- h_tedatabase_connect ptr h u p n
		if st == False then (errorMessage ptr) >>= error else do return ptr
		
	close db = (tedatabase_close db)


instance TeDatabases TeDatabase where

	loadLayer db  ln = TerraHS.Misc.Object.new (TeLayer ln) >>= \layer -> (tedatabase_loadLayer db layer) >>= \st ->
		if st == True then return layer else do  error ("layer nao encontrado")
		
	errorMessage db = h_tedatabase_errorMessage db >>= peekCString >>= return	

	loadRaster db ln = do
		layer <- loadLayer db ln
		ptr <- getRaster layer
		-- convert to haskell object
		raster <- fromPointer ptr 
		return raster
		
	importRaster ptr ln	rs  = do
		l <- newCString ln
		rsptr <- new rs
		teimportraster l rsptr ptr  
		
	importRasterWParameter ptr ln dummy rs  = do
		l <- newCString ln
		rsptr <- new rs
		teraster_setdummy rsptr dummy
		teimportraster l rsptr ptr  




instance Pointer TeDatabase where
	new (TeMySQL _ _ _ _)  = (temysql_new)
	new TePostgreSQL = error ("nao implementado")
		
	delete db = (tedatabase_destroy db)			
	
	
-----------------------------------------------------------------------------------------
-- terralib functions
-----------------------------------------------------------------------------------------

-- instanciação (MySQL)	 
foreign import stdcall unsafe "c_temysql_new"  temysql_new :: Prelude.IO TeDatabasePtr
-- destruição ponteiro
foreign import stdcall unsafe "c_tedatabase_destroy" tedatabase_destroy :: TeDatabasePtr -> Prelude.IO ()
foreign import stdcall unsafe "c_tedatabase_connect" h_tedatabase_connect :: TeDatabasePtr -> CString -> CString -> CString -> CString -> Prelude.IO Bool
-- fechando um banco de dados
foreign import stdcall unsafe "c_tedatabase_close" tedatabase_close :: TeDatabasePtr -> Prelude.IO ()
foreign import stdcall unsafe "c_tedatabase_errorMessage"  h_tedatabase_errorMessage :: TeDatabasePtr -> Prelude.IO CString
-- carrega um determinado layer (com status)
foreign import stdcall unsafe "c_tedatabase_loadLayer" tedatabase_loadLayer :: TeDatabasePtr -> TeLayerPtr -> Prelude.IO Bool
-- raster
foreign import stdcall unsafe  "c_teimportraster" teimportraster ::  CString -> TeRasterPtr -> TeDatabasePtr -> Prelude.IO Bool