{-# LANGUAGE DataKinds #-}

module Database.Esqueleto.Postgis.Editor
  ( st_addpoint
  , st_collectionextract
  , st_flipcoordinates
  , st_force2d
  , st_force3d
  , st_force4d
  , st_forcecollection
  , st_forcepolygonccw
  , st_forcepolygoncw
  , st_multi
  , st_normalize
  , st_reverse
  , st_segmentize
  , st_setpoint
  , st_snaptogrid
  , st_snap
  ) where

import Database.Esqueleto.Postgis.Geometry (Postgis, SpatialType(..))
import Database.Esqueleto.Experimental (SqlExpr, Value)
import Database.Esqueleto.Internal.Internal (unsafeSqlFunction)

-- | Adds a point to a linestring at a given position (0-indexed).
--   https://postgis.net/docs/ST_AddPoint.html
st_addpoint ::
  SqlExpr (Value (Postgis 'Geometry a)) -> -- ^ linestring
  SqlExpr (Value (Postgis 'Geometry a)) -> -- ^ point
  SqlExpr (Value Int) ->                   -- ^ position
  SqlExpr (Value (Postgis 'Geometry a))
st_addpoint :: forall a.
SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value Int)
-> SqlExpr (Value (Postgis 'Geometry a))
st_addpoint SqlExpr (Value (Postgis 'Geometry a))
a SqlExpr (Value (Postgis 'Geometry a))
b SqlExpr (Value Int)
n = Builder
-> (SqlExpr (Value (Postgis 'Geometry a)),
    SqlExpr (Value (Postgis 'Geometry a)), SqlExpr (Value Int))
-> SqlExpr (Value (Postgis 'Geometry a))
forall a b.
UnsafeSqlFunctionArgument a =>
Builder -> a -> SqlExpr (Value b)
unsafeSqlFunction Builder
"ST_AddPoint" (SqlExpr (Value (Postgis 'Geometry a))
a, SqlExpr (Value (Postgis 'Geometry a))
b, SqlExpr (Value Int)
n)

-- | Extracts sub-geometries of a specified type from a collection.
--   Type: 1=POINT, 2=LINESTRING, 3=POLYGON.
--   https://postgis.net/docs/ST_CollectionExtract.html
st_collectionextract ::
  SqlExpr (Value (Postgis 'Geometry a)) ->
  SqlExpr (Value Int) ->
  SqlExpr (Value (Postgis 'Geometry a))
st_collectionextract :: forall a.
SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value Int) -> SqlExpr (Value (Postgis 'Geometry a))
st_collectionextract SqlExpr (Value (Postgis 'Geometry a))
a SqlExpr (Value Int)
t = Builder
-> (SqlExpr (Value (Postgis 'Geometry a)), SqlExpr (Value Int))
-> SqlExpr (Value (Postgis 'Geometry a))
forall a b.
UnsafeSqlFunctionArgument a =>
Builder -> a -> SqlExpr (Value b)
unsafeSqlFunction Builder
"ST_CollectionExtract" (SqlExpr (Value (Postgis 'Geometry a))
a, SqlExpr (Value Int)
t)

-- | Swaps X and Y coordinates.
--   https://postgis.net/docs/ST_FlipCoordinates.html
st_flipcoordinates ::
  SqlExpr (Value (Postgis 'Geometry a)) ->
  SqlExpr (Value (Postgis 'Geometry a))
st_flipcoordinates :: forall a.
SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value (Postgis 'Geometry a))
st_flipcoordinates SqlExpr (Value (Postgis 'Geometry a))
a = Builder
-> SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value (Postgis 'Geometry a))
forall a b.
UnsafeSqlFunctionArgument a =>
Builder -> a -> SqlExpr (Value b)
unsafeSqlFunction Builder
"ST_FlipCoordinates" SqlExpr (Value (Postgis 'Geometry a))
a

-- | Forces the geometry into 2D mode.
--   https://postgis.net/docs/ST_Force2D.html
st_force2d ::
  SqlExpr (Value (Postgis 'Geometry a)) ->
  SqlExpr (Value (Postgis 'Geometry a))
st_force2d :: forall a.
SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value (Postgis 'Geometry a))
st_force2d SqlExpr (Value (Postgis 'Geometry a))
a = Builder
-> SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value (Postgis 'Geometry a))
forall a b.
UnsafeSqlFunctionArgument a =>
Builder -> a -> SqlExpr (Value b)
unsafeSqlFunction Builder
"ST_Force2D" SqlExpr (Value (Postgis 'Geometry a))
a

-- | Forces the geometry into 3D (XYZ) mode.
--   https://postgis.net/docs/ST_Force3D.html
st_force3d ::
  SqlExpr (Value (Postgis 'Geometry a)) ->
  SqlExpr (Value (Postgis 'Geometry a))
st_force3d :: forall a.
SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value (Postgis 'Geometry a))
st_force3d SqlExpr (Value (Postgis 'Geometry a))
a = Builder
-> SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value (Postgis 'Geometry a))
forall a b.
UnsafeSqlFunctionArgument a =>
Builder -> a -> SqlExpr (Value b)
unsafeSqlFunction Builder
"ST_Force3D" SqlExpr (Value (Postgis 'Geometry a))
a

-- | Forces the geometry into 4D (XYZM) mode.
--   https://postgis.net/docs/ST_Force4D.html
st_force4d ::
  SqlExpr (Value (Postgis 'Geometry a)) ->
  SqlExpr (Value (Postgis 'Geometry a))
st_force4d :: forall a.
SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value (Postgis 'Geometry a))
st_force4d SqlExpr (Value (Postgis 'Geometry a))
a = Builder
-> SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value (Postgis 'Geometry a))
forall a b.
UnsafeSqlFunctionArgument a =>
Builder -> a -> SqlExpr (Value b)
unsafeSqlFunction Builder
"ST_Force4D" SqlExpr (Value (Postgis 'Geometry a))
a

-- | Converts the geometry into a geometry collection.
--   https://postgis.net/docs/ST_ForceCollection.html
st_forcecollection ::
  SqlExpr (Value (Postgis 'Geometry a)) ->
  SqlExpr (Value (Postgis 'Geometry a))
st_forcecollection :: forall a.
SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value (Postgis 'Geometry a))
st_forcecollection SqlExpr (Value (Postgis 'Geometry a))
a = Builder
-> SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value (Postgis 'Geometry a))
forall a b.
UnsafeSqlFunctionArgument a =>
Builder -> a -> SqlExpr (Value b)
unsafeSqlFunction Builder
"ST_ForceCollection" SqlExpr (Value (Postgis 'Geometry a))
a

-- | Forces polygon rings to counter-clockwise orientation.
--   https://postgis.net/docs/ST_ForcePolygonCCW.html
st_forcepolygonccw ::
  SqlExpr (Value (Postgis 'Geometry a)) ->
  SqlExpr (Value (Postgis 'Geometry a))
st_forcepolygonccw :: forall a.
SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value (Postgis 'Geometry a))
st_forcepolygonccw SqlExpr (Value (Postgis 'Geometry a))
a = Builder
-> SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value (Postgis 'Geometry a))
forall a b.
UnsafeSqlFunctionArgument a =>
Builder -> a -> SqlExpr (Value b)
unsafeSqlFunction Builder
"ST_ForcePolygonCCW" SqlExpr (Value (Postgis 'Geometry a))
a

-- | Forces polygon rings to clockwise orientation.
--   https://postgis.net/docs/ST_ForcePolygonCW.html
st_forcepolygoncw ::
  SqlExpr (Value (Postgis 'Geometry a)) ->
  SqlExpr (Value (Postgis 'Geometry a))
st_forcepolygoncw :: forall a.
SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value (Postgis 'Geometry a))
st_forcepolygoncw SqlExpr (Value (Postgis 'Geometry a))
a = Builder
-> SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value (Postgis 'Geometry a))
forall a b.
UnsafeSqlFunctionArgument a =>
Builder -> a -> SqlExpr (Value b)
unsafeSqlFunction Builder
"ST_ForcePolygonCW" SqlExpr (Value (Postgis 'Geometry a))
a

-- | Returns the geometry as a multi-type (e.g. POINT -> MULTIPOINT).
--   https://postgis.net/docs/ST_Multi.html
st_multi ::
  SqlExpr (Value (Postgis 'Geometry a)) ->
  SqlExpr (Value (Postgis 'Geometry a))
st_multi :: forall a.
SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value (Postgis 'Geometry a))
st_multi SqlExpr (Value (Postgis 'Geometry a))
a = Builder
-> SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value (Postgis 'Geometry a))
forall a b.
UnsafeSqlFunctionArgument a =>
Builder -> a -> SqlExpr (Value b)
unsafeSqlFunction Builder
"ST_Multi" SqlExpr (Value (Postgis 'Geometry a))
a

-- | Returns the geometry in its canonical (normalized) form.
--   https://postgis.net/docs/ST_Normalize.html
st_normalize ::
  SqlExpr (Value (Postgis 'Geometry a)) ->
  SqlExpr (Value (Postgis 'Geometry a))
st_normalize :: forall a.
SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value (Postgis 'Geometry a))
st_normalize SqlExpr (Value (Postgis 'Geometry a))
a = Builder
-> SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value (Postgis 'Geometry a))
forall a b.
UnsafeSqlFunctionArgument a =>
Builder -> a -> SqlExpr (Value b)
unsafeSqlFunction Builder
"ST_Normalize" SqlExpr (Value (Postgis 'Geometry a))
a

-- | Returns the geometry with vertex order reversed.
--   https://postgis.net/docs/ST_Reverse.html
st_reverse ::
  SqlExpr (Value (Postgis 'Geometry a)) ->
  SqlExpr (Value (Postgis 'Geometry a))
st_reverse :: forall a.
SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value (Postgis 'Geometry a))
st_reverse SqlExpr (Value (Postgis 'Geometry a))
a = Builder
-> SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value (Postgis 'Geometry a))
forall a b.
UnsafeSqlFunctionArgument a =>
Builder -> a -> SqlExpr (Value b)
unsafeSqlFunction Builder
"ST_Reverse" SqlExpr (Value (Postgis 'Geometry a))
a

-- | Segmentizes a geometry so no segment is longer than the given distance.
--   https://postgis.net/docs/ST_Segmentize.html
st_segmentize ::
  SqlExpr (Value (Postgis 'Geometry a)) ->
  SqlExpr (Value Double) ->
  SqlExpr (Value (Postgis 'Geometry a))
st_segmentize :: forall a.
SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value Double) -> SqlExpr (Value (Postgis 'Geometry a))
st_segmentize SqlExpr (Value (Postgis 'Geometry a))
a SqlExpr (Value Double)
d = Builder
-> (SqlExpr (Value (Postgis 'Geometry a)), SqlExpr (Value Double))
-> SqlExpr (Value (Postgis 'Geometry a))
forall a b.
UnsafeSqlFunctionArgument a =>
Builder -> a -> SqlExpr (Value b)
unsafeSqlFunction Builder
"ST_Segmentize" (SqlExpr (Value (Postgis 'Geometry a))
a, SqlExpr (Value Double)
d)

-- | Replaces a point of a linestring at a given 0-based index.
--   https://postgis.net/docs/ST_SetPoint.html
st_setpoint ::
  SqlExpr (Value (Postgis 'Geometry a)) -> -- ^ linestring
  SqlExpr (Value Int) ->                   -- ^ 0-based index
  SqlExpr (Value (Postgis 'Geometry a)) -> -- ^ new point
  SqlExpr (Value (Postgis 'Geometry a))
st_setpoint :: forall a.
SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value Int)
-> SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value (Postgis 'Geometry a))
st_setpoint SqlExpr (Value (Postgis 'Geometry a))
a SqlExpr (Value Int)
n SqlExpr (Value (Postgis 'Geometry a))
p = Builder
-> (SqlExpr (Value (Postgis 'Geometry a)), SqlExpr (Value Int),
    SqlExpr (Value (Postgis 'Geometry a)))
-> SqlExpr (Value (Postgis 'Geometry a))
forall a b.
UnsafeSqlFunctionArgument a =>
Builder -> a -> SqlExpr (Value b)
unsafeSqlFunction Builder
"ST_SetPoint" (SqlExpr (Value (Postgis 'Geometry a))
a, SqlExpr (Value Int)
n, SqlExpr (Value (Postgis 'Geometry a))
p)

-- | Snaps all points of a geometry to a regular grid of the given size.
--   https://postgis.net/docs/ST_SnapToGrid.html
st_snaptogrid ::
  SqlExpr (Value (Postgis 'Geometry a)) ->
  SqlExpr (Value Double) ->
  SqlExpr (Value (Postgis 'Geometry a))
st_snaptogrid :: forall a.
SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value Double) -> SqlExpr (Value (Postgis 'Geometry a))
st_snaptogrid SqlExpr (Value (Postgis 'Geometry a))
a SqlExpr (Value Double)
d = Builder
-> (SqlExpr (Value (Postgis 'Geometry a)), SqlExpr (Value Double))
-> SqlExpr (Value (Postgis 'Geometry a))
forall a b.
UnsafeSqlFunctionArgument a =>
Builder -> a -> SqlExpr (Value b)
unsafeSqlFunction Builder
"ST_SnapToGrid" (SqlExpr (Value (Postgis 'Geometry a))
a, SqlExpr (Value Double)
d)

-- | Snaps vertices of one geometry to vertices and edges of another within a tolerance.
--   https://postgis.net/docs/ST_Snap.html
st_snap ::
  SqlExpr (Value (Postgis 'Geometry a)) ->
  SqlExpr (Value (Postgis 'Geometry a)) ->
  SqlExpr (Value Double) ->
  SqlExpr (Value (Postgis 'Geometry a))
st_snap :: forall a.
SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value (Postgis 'Geometry a))
-> SqlExpr (Value Double)
-> SqlExpr (Value (Postgis 'Geometry a))
st_snap SqlExpr (Value (Postgis 'Geometry a))
a SqlExpr (Value (Postgis 'Geometry a))
b SqlExpr (Value Double)
d = Builder
-> (SqlExpr (Value (Postgis 'Geometry a)),
    SqlExpr (Value (Postgis 'Geometry a)), SqlExpr (Value Double))
-> SqlExpr (Value (Postgis 'Geometry a))
forall a b.
UnsafeSqlFunctionArgument a =>
Builder -> a -> SqlExpr (Value b)
unsafeSqlFunction Builder
"ST_Snap" (SqlExpr (Value (Postgis 'Geometry a))
a, SqlExpr (Value (Postgis 'Geometry a))
b, SqlExpr (Value Double)
d)