{-- 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 TeLayer TerraLib class

	 In TerraLib, a layer is a collection of geometries that share the same 
	geographical projection, and are related in some way (e.g. a shapefile).
	 A layer has a pointer to a database that effectively stores its atributes
	 and geometries.

	 More information - <http://www.terralib.org>
-}
module TerraHS.TerraLib.TeLayer 	where


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

-- locais
import TerraHS.Algebras.Base.Object
import TerraHS.TerraLib.TeGeometry
import TerraHS.TerraLib.TePoint
import TerraHS.TerraLib.TeLine2D
import TerraHS.TerraLib.TePolygon
import TerraHS.TerraLib.TeCell
import TerraHS.TerraLib.TeTable 
--import TerraHS.TerraLib.TeRaster 

--import {-# SOURCE #-}TerraHS.TerraLib.TeDatabase (TeDatabasePtr)
import TerraHS.TerraLib.TeDatabase



----------------- projection

data TeDatum = TeSAD69 deriving (Show)

type LongO = Double

data TeProjection = TeNoProjection | TeLatLong TeDatum  | TeUTM TeDatum LongO deriving (Show)

type TeProjectionPtr = Foreign.Ptr.Ptr TeProjection


class Layers l where
	-- | Returns the layer name
	name :: (Foreign.Ptr.Ptr l) -> Prelude.IO String
	
	-- | Load information about a particular layer 
	loadLayer :: TeDatabasePtr  -> String -> Prelude.IO  (Foreign.Ptr.Ptr l)
	
	--getRaster :: (Foreign.Ptr.Ptr l) -> Prelude.IO TeRasterPtr
	getPolygons :: (Foreign.Ptr.Ptr l) -> Prelude.IO [TeGeometry]
	
	-- |  Saves an attribute table into the database where layer is stored 
	saveTable :: (Foreign.Ptr.Ptr l) -> TeTable ->  Prelude.IO Bool
	-- | Adds a set of points to a layer
	addPoints :: (Foreign.Ptr.Ptr l) ->  TePointSet -> Prelude.IO Bool
	
	addLines :: (Foreign.Ptr.Ptr l) ->  TeLineSet -> Prelude.IO Bool
	
	addCells :: (Foreign.Ptr.Ptr l) ->  TeCellSet -> Prelude.IO Bool
	
	addPolygons :: (Foreign.Ptr.Ptr l) ->  TePolygonSet -> Prelude.IO Bool

	
-- | The type  @TeLayer@ represents a geographic layer
--data TeLayer = TeLayer String  | TeLayerDb String TeDatabasePtr deriving (Show)
data TeLayer = TeLayer String  TeDatabasePtr deriving (Show)

-- | The type @TeLayerPtr@ is a pointer to @TeLayer@
type TeLayerPtr = Foreign.Ptr.Ptr TeLayer

instance Layers TeLayer where
	-- return layer name
	name ptr  =  telayer_name ptr >>= peekCString >>= return
	
	loadLayer db  ln = new (TeLayer ln db) >>= \layer -> (tedatabase_loadLayer db layer) >>= \st ->
		if st == True then return layer else do  error ("layer nao encontrado")

	--getRaster l = telayer_raster l
	
	saveTable layer (TeTable name attrs values) = do
		table <- new (TeTable name attrs values)
		st <- createAttributeTable layer table 
		addValues values table
		st1 <- telayer_saveattributetable layer table 
		return (st && st1)
		
	addPoints layer ps = new ps >>= telayer_addpoints layer
	
	addLines layer ls = new ls >>= telayer_addlines layer
	
	addCells layer cs = new cs >>= telayer_addcells layer
	
	addPolygons layer ps = new ps >>= telayer_addpolygons layer
	
	getPolygons ptr  = telayer_gettepolygons ptr >>= \ps -> size ps >>= (polygonset2geometryset ps 0) >>= return
		where
		telayer_gettepolygons layer = (new  (TePolygonSet [])) >>= \ps -> (h_telayer_gettepolygons layer ps) >> return ps
	

			
	
--instanciação-----------------------------------------------------------

instance Pointer TeLayer where
	new (TeLayer ln db) =  (newCString ln) >>=  (tedatabase_newLayer db ) >>= return
	--new (TeLayer ln) = (newCString ln) >>= h_telayer_new >>= return
	delete l = error "not implemented"
	
instance Pointer TeProjection where
	new (TeLatLong _)  =  (newCString "SAD69") >>= \dname -> (telatlong_new dname ) >>= return
	new  (TeUTM _ longO ) = (newCString "SAD69") >>= \dname -> (teutm_new dname longO) >>= return
		
	delete pr =	error "delete: not implemented"

-- chamadas de funções da interface "C"	

-- carrega um determinado layer (com status)
foreign import stdcall unsafe "c_tedatabase_loadLayer" tedatabase_loadLayer :: TeDatabasePtr -> TeLayerPtr -> Prelude.IO Bool

foreign import stdcall unsafe "c_telayer_gettepolygons" h_telayer_gettepolygons :: TeLayerPtr-> TePolygonSetPtr ->  Prelude.IO ()
foreign import stdcall unsafe "c_telayer_name"  telayer_name :: TeLayerPtr -> Prelude.IO CString
--foreign import stdcall unsafe "c_telayer_raster"  telayer_raster :: TeLayerPtr -> Prelude.IO TeRasterPtr
foreign import stdcall unsafe "c_telayer_new" h_telayer_new :: CString -> Prelude.IO TeLayerPtr
foreign import stdcall unsafe "c_telayer_addcolumn" telayer_addcolumn ::  TeLayerPtr -> CString -> Prelude.IO ()
foreign import stdcall unsafe "c_telayer_insertvalue" telayer_insertvalue ::  TeLayerPtr -> CString -> CString -> CString -> Prelude.IO ()
foreign import stdcall unsafe "c_createAttributeTable" createAttributeTable ::  TeLayerPtr -> TeTablePtr  -> Prelude.IO Bool
foreign import stdcall unsafe "c_telayer_saveattributetable" telayer_saveattributetable ::  TeLayerPtr -> TeTablePtr  -> Prelude.IO Bool
foreign import stdcall unsafe "c_tedatabase_newLayer" tedatabase_newLayer :: TeDatabasePtr -> CString -> Prelude.IO TeLayerPtr
foreign import stdcall unsafe "c_telayer_addpoints" telayer_addpoints :: TeLayerPtr  -> TePointSetPtr -> Prelude.IO Bool
foreign import stdcall unsafe "c_telayer_addlines" telayer_addlines :: TeLayerPtr  -> TeLineSetPtr -> Prelude.IO Bool
foreign import stdcall unsafe "c_telayer_addcells" telayer_addcells :: TeLayerPtr  -> TeCellSetPtr -> Prelude.IO Bool
foreign import stdcall unsafe "c_telayer_addpolygons" telayer_addpolygons :: TeLayerPtr  -> TePolygonSetPtr -> Prelude.IO Bool

foreign import stdcall unsafe "c_telayer_setprojection" telayer_setprojection :: TeLayerPtr  -> TeProjectionPtr -> Prelude.IO ()

---



foreign import stdcall unsafe "c_tedatabase_newLayer2" tedatabase_newLayer2 :: TeDatabasePtr -> CString -> TeProjectionPtr -> Prelude.IO TeLayerPtr

foreign import stdcall unsafe "c_telatlong_new" telatlong_new ::  CString -> Prelude.IO TeProjectionPtr 

foreign import stdcall unsafe "c_teutm_new" teutm_new ::  CString -> Double -> Prelude.IO TeProjectionPtr