{-- 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 @TePoint@ 
		x, y,
		
		-- ** Operations on @TePointSet@ 
		getListPoint,
	)
	 where

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

import TerraHS.Misc.Object

import TerraHS.TerraLib.TeCoord2D


-- | 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


-- | Returns the X componente of the coordinate 
x :: TePoint -> Double
x (TePoint coord ) = ( cx coord )

-- | Returns the Y componente of the coordinate 
y :: TePoint -> Double
y (TePoint coord ) = ( cy coord )

-- | Returns a @TePoint@ list 
getListPoint :: TePointSet -> [TePoint]
getListPoint (TePointSet ps) = ps

pointId :: TePointPtr -> String -> IO ()
pointId ptr str = newCString str >>= (tepoint_setobjectid ptr) >>= return
		
instance Pointer TePoint where

	new pt = tepoint_new (x pt) (y 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 <- TerraHS.Misc.Object.new (TePointSet [])
		tepointSetAdd ptr xs 0
		return ptr
		where
		tepointSetAdd ptr [] _ = error "erro"
		tepointSetAdd ptr [x] i = TerraHS.Misc.Object.new x >>= \pt -> pointId pt (show i)  >> tepointset_addtepoint ptr pt 
		tepointSetAdd ptr (x:xs) i = TerraHS.Misc.Object.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 

		
---------------- 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 ()