-- etldoc: layer_lm[shape=record fillcolor=lightpink, style="rounded,filled",
-- etldoc:     label="layer_lm | <z12> z12 | <z13> z13 | <z14_> z14+" ] ;

CREATE OR REPLACE FUNCTION layer_lm(bbox geometry, zoom_level integer, pixel_width numeric)
    RETURNS TABLE
            (
                osm_id   bigint,
                geometry geometry,
                name     text,
                name_en  text,
                name_de  text,
                tags     hstore,
                class    text,
                subclass text,
                agg_stop integer,
                layer    integer,
                level    integer,
                "rank"   int
            )
AS
$$
SELECT osm_id_hash                                  AS osm_id,
       geometry,
       NULLIF(name, '')                             AS name,
       COALESCE(NULLIF(name_en, ''), name)          AS name_en,
       COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
       tags,
       lm_class(subclass, mapping_key)             AS class,
       subclass                                      AS subclass,
       agg_stop,
       NULLIF(layer, 0)                             AS layer,
       "level",
       row_number() OVER (
           PARTITION BY LabelGrid(geometry, 100 * pixel_width)
           ORDER BY CASE WHEN name = '' THEN 2000 ELSE lm_class_rank(lm_class(subclass, mapping_key)) END ASC
           )::int                                   AS "rank"
FROM (
         -- etldoc: osm_lm_point ->  layer_lm:z12
         -- etldoc: osm_lm_point ->  layer_lm:z13
         SELECT *,
                osm_id * 10 AS osm_id_hash
         FROM osm_lm_point
         WHERE geometry && bbox
           AND zoom_level BETWEEN 12 AND 13
           AND ((subclass = 'station' AND mapping_key = 'railway')
             OR subclass IN ('halt', 'ferry_terminal'))

         UNION ALL

         -- etldoc: osm_lm_point ->  layer_lm:z14_
         SELECT *,
                osm_id * 10 AS osm_id_hash
         FROM osm_lm_point
         WHERE geometry && bbox
           AND zoom_level >= 14

         UNION ALL

         -- etldoc: osm_lm_polygon ->  layer_lm:z12
         -- etldoc: osm_lm_polygon ->  layer_lm:z13
         SELECT *,
                NULL::integer AS agg_stop,
                CASE
                    WHEN osm_id < 0 THEN -osm_id * 10 + 4
                    ELSE osm_id * 10 + 1
                    END       AS osm_id_hash
         FROM osm_lm_polygon
         WHERE geometry && bbox
           AND zoom_level BETWEEN 12 AND 13
           AND ((subclass = 'station' AND mapping_key = 'railway')
             OR subclass IN ('halt', 'ferry_terminal'))

         UNION ALL

         -- etldoc: osm_lm_polygon ->  layer_lm:z14_
         SELECT *,
                NULL::integer AS agg_stop,
                CASE
                    WHEN osm_id < 0 THEN -osm_id * 10 + 4
                    ELSE osm_id * 10 + 1
                    END       AS osm_id_hash
         FROM osm_lm_polygon
         WHERE geometry && bbox
           AND zoom_level >= 14
     ) AS lm_union
ORDER BY "rank"
$$ LANGUAGE SQL STABLE
                PARALLEL SAFE;
-- TODO: Check if the above can be made STRICT -- i.e. if pixel_width could be NULL
