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

TePoint: A class for handling 2D Points. 

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

		
		-- * The @TePointSet@ type
		TePointSet (..),
		
		-- * The @TePointSetPtr@ type
		TePointSetPtr,
	

		-- ** Operations on @TePointSet@ 
		--getListPoint,
	)
	 where

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

import TerraHS.Algebras.Base.Object

import TerraHS.TerraLib.TeCoord2D

import TerraHS.Algebras.Spatial.Points

-- | The type  @TePoint@ represents 2D Points. 
data TePoint = TePoint TeCoord2D deriving (Eq,Show,Ord)

-- | The type @TePointPtr@ is a pointer to @TePoint@
type TePointPtr = Foreign.Ptr.Ptr TePoint

-- | The type  @TePointSet@ represents  a sets of 2D Points. 
data TePointSet = TePointSet [TePoint]

-- | The type @TePointSetPtr@ is a pointer to @TePointSet@
type TePointSetPtr = Foreign.Ptr.Ptr TePointSet
	
pointId ptr str = newCString str >>= (tepoint_setobjectid ptr) >>= return

instance Pointer TePoint where

	new pt = tepoint_new (getX pt) (getY pt) >>= return

	delete ptr = (tepoint_destroy ptr)		

	fromPointer ptr = (tepoint_getx ptr ) >>= \x -> (tepoint_gety ptr ) >>= \y -> return (TePoint (x, y))

instance Pointer TePointSet where
	new (TePointSet []) = tepointset_new
	new (TePointSet xs) = do
		ptr <- new (TePointSet [])
		tepointSetAdd ptr xs 0
		return ptr
		where
		tepointSetAdd ptr [] _ = error "erro"
		tepointSetAdd ptr [x] i = new x >>= \pt -> pointId pt (show i)  >> tepointset_addtepoint ptr pt 
		tepointSetAdd ptr (x:xs) i = new x >>= \pt -> pointId pt (show i)  >> tepointset_addtepoint ptr pt >> tepointSetAdd ptr xs (i+1)
				
	delete ptr = (tepointset_destroy ptr)

instance Size TePointSet where

	size ptr = (tepointset_size ptr)
		
	
instance Element TePointSet TePoint where

	getElement ptr i = tepointset_gettepoint ptr i >>= fromPointer >>= return 
	
	
---------------- Algebra

instance Points TePoint Double where
	createPoint cx cy = (TePoint (cx, cy) )
	getX (TePoint (cx, cy)) = cx
	getY (TePoint (cx, cy)) = cy


		
---------------- TePoint ----------------------------------------------------
foreign import stdcall unsafe "c_tepoint_new" tepoint_new :: Double -> Double ->  Prelude.IO TePointPtr
foreign import stdcall unsafe "c_tepoint_destroy" tepoint_destroy :: TePointPtr -> Prelude.IO ()
foreign import stdcall unsafe "c_tepoint_getx" tepoint_getx :: TePointPtr -> Prelude.IO Double
foreign import stdcall unsafe "c_tepoint_gety" tepoint_gety :: TePointPtr -> Prelude.IO Double

---------------- TePointSet ----------------------------------------------------
foreign import stdcall unsafe "c_tepointset_new" tepointset_new :: Prelude.IO TePointSetPtr
foreign import stdcall unsafe "c_tepointset_destroy" tepointset_destroy :: TePointSetPtr -> Prelude.IO ()
foreign import stdcall unsafe "c_tepointset_size" tepointset_size :: TePointSetPtr -> Prelude.IO Int32
foreign import stdcall unsafe "c_tepointset_gettepoint" tepointset_gettepoint :: TePointSetPtr -> Int32 -> Prelude.IO TePointPtr
foreign import stdcall unsafe "c_tepoint_getobjectid" tepoint_getobjectid :: TePointPtr -> Prelude.IO CString
foreign import stdcall unsafe "c_tepoint_setobjectid" tepoint_setobjectid :: TePointPtr -> CString -> Prelude.IO ()
foreign import stdcall unsafe "c_tepointset_addtepoint" tepointset_addtepoint :: TePointSetPtr -> TePointPtr -> Prelude.IO ()