-- Zoom-dependent tile functions for Martin.
-- These apply geometry simplification and feature filtering so that
-- low-zoom tiles contain fewer, simpler features.

--------------------------------------------------------------------------------
-- planet_osm_polygon
--------------------------------------------------------------------------------
CREATE OR REPLACE FUNCTION tile_polygon(z integer, x integer, y integer)
RETURNS bytea AS $$
DECLARE
  bounds geometry;
  tolerance double precision;
  result bytea;
BEGIN
  bounds := ST_TileEnvelope(z, x, y);

  -- Simplification tolerance scales with zoom: lower zoom = more aggressive
  tolerance := CASE
    WHEN z >= 13 THEN 0        -- full detail
    WHEN z >= 11 THEN 1        -- light simplification
    WHEN z >= 9  THEN 10       -- moderate
    ELSE 50                     -- heavy
  END;

  WITH features AS (
    SELECT
      osm_id,
      name,
      building,
      landuse,
      "natural",
      amenity,
      leisure,
      water,
      waterway,
      CASE
        WHEN tolerance = 0 THEN ST_AsMVTGeom(way, bounds)
        ELSE ST_AsMVTGeom(
          ST_Simplify(way, tolerance, true),
          bounds
        )
      END AS geom
    FROM planet_osm_polygon
    WHERE way && bounds
      -- Feature filtering by zoom level:
      AND CASE
        -- zoom 8-9: only water, large forests/parks
        WHEN z < 10 THEN
          "natural" IN ('water', 'wood') OR landuse IN ('forest', 'reservoir')
        -- zoom 10-11: add more landuse
        WHEN z < 12 THEN
          "natural" IN ('water', 'wood', 'wetland', 'heath', 'scrub')
          OR landuse IN ('forest', 'reservoir', 'residential', 'industrial',
                         'commercial', 'farmland', 'meadow', 'grass')
          OR leisure IN ('park', 'nature_reserve', 'garden')
        -- zoom 12: add buildings (large only)
        WHEN z < 13 THEN
          "natural" IS NOT NULL OR landuse IS NOT NULL OR leisure IS NOT NULL
          OR water IS NOT NULL
          OR (building IS NOT NULL AND ST_Area(way) > 5000)
        -- zoom 13+: everything
        ELSE true
      END
  )
  SELECT ST_AsMVT(features, 'planet_osm_polygon') INTO result FROM features;

  RETURN result;
END;
$$ LANGUAGE plpgsql STABLE PARALLEL SAFE;

--------------------------------------------------------------------------------
-- planet_osm_line
--------------------------------------------------------------------------------
CREATE OR REPLACE FUNCTION tile_line(z integer, x integer, y integer)
RETURNS bytea AS $$
DECLARE
  bounds geometry;
  tolerance double precision;
  result bytea;
BEGIN
  bounds := ST_TileEnvelope(z, x, y);

  tolerance := CASE
    WHEN z >= 13 THEN 0
    WHEN z >= 11 THEN 5
    ELSE 20
  END;

  WITH features AS (
    SELECT
      osm_id,
      name,
      highway,
      railway,
      waterway,
      CASE
        WHEN tolerance = 0 THEN ST_AsMVTGeom(way, bounds)
        ELSE ST_AsMVTGeom(
          ST_Simplify(way, tolerance, true),
          bounds
        )
      END AS geom
    FROM planet_osm_line
    WHERE way && bounds
      AND CASE
        -- zoom 10-11: only major roads and rivers
        WHEN z < 12 THEN
          highway IN ('motorway', 'trunk', 'primary', 'secondary')
          OR railway IN ('rail')
          OR waterway IN ('river', 'canal')
        -- zoom 12: add tertiary roads
        WHEN z < 13 THEN
          highway IN ('motorway', 'trunk', 'primary', 'secondary',
                      'tertiary', 'motorway_link', 'trunk_link')
          OR railway IS NOT NULL
          OR waterway IS NOT NULL
        -- zoom 13+: everything
        ELSE true
      END
  )
  SELECT ST_AsMVT(features, 'planet_osm_line') INTO result FROM features;

  RETURN result;
END;
$$ LANGUAGE plpgsql STABLE PARALLEL SAFE;

--------------------------------------------------------------------------------
-- planet_osm_point
--------------------------------------------------------------------------------
CREATE OR REPLACE FUNCTION tile_point(z integer, x integer, y integer)
RETURNS bytea AS $$
DECLARE
  bounds geometry;
  result bytea;
BEGIN
  bounds := ST_TileEnvelope(z, x, y);

  WITH features AS (
    SELECT
      osm_id,
      name,
      place,
      amenity,
      shop,
      tourism,
      "natural",
      ST_AsMVTGeom(way, bounds) AS geom
    FROM planet_osm_point
    WHERE way && bounds
      AND CASE
        -- zoom 12: only cities/towns/villages and major POIs
        WHEN z < 13 THEN
          place IN ('city', 'town', 'village')
        -- zoom 13: add hamlets and named POIs
        WHEN z < 14 THEN
          place IS NOT NULL
          OR (name IS NOT NULL AND (amenity IS NOT NULL OR tourism IS NOT NULL))
        -- zoom 14+: everything
        ELSE true
      END
  )
  SELECT ST_AsMVT(features, 'planet_osm_point') INTO result FROM features;

  RETURN result;
END;
$$ LANGUAGE plpgsql STABLE PARALLEL SAFE;

--------------------------------------------------------------------------------
-- planet_osm_roads
--------------------------------------------------------------------------------
CREATE OR REPLACE FUNCTION tile_roads(z integer, x integer, y integer)
RETURNS bytea AS $$
DECLARE
  bounds geometry;
  tolerance double precision;
  result bytea;
BEGIN
  bounds := ST_TileEnvelope(z, x, y);

  tolerance := CASE
    WHEN z >= 10 THEN 0
    WHEN z >= 8  THEN 10
    ELSE 50
  END;

  WITH features AS (
    SELECT
      osm_id,
      name,
      highway,
      ref,
      CASE
        WHEN tolerance = 0 THEN ST_AsMVTGeom(way, bounds)
        ELSE ST_AsMVTGeom(
          ST_Simplify(way, tolerance, true),
          bounds
        )
      END AS geom
    FROM planet_osm_roads
    WHERE way && bounds
      AND CASE
        -- zoom 6-7: motorways only
        WHEN z < 8 THEN
          highway IN ('motorway', 'trunk')
        -- zoom 8-9: add primary roads
        WHEN z < 10 THEN
          highway IN ('motorway', 'trunk', 'primary')
        -- zoom 10+: everything in the roads table
        ELSE true
      END
  )
  SELECT ST_AsMVT(features, 'planet_osm_roads') INTO result FROM features;

  RETURN result;
END;
$$ LANGUAGE plpgsql STABLE PARALLEL SAFE;