-- World overview tile processing (z0-9)
-- Based on openmaptiles.org schema, stripped to layers relevant at world zoom.
-- No buildings, housenumbers, or POIs — those only appear at z12+.

preferred_language = nil
preferred_language_attribute = "name:latin"
default_language_attribute = "name_int"
additional_languages = { }

function init_function()
end
function exit_function()
end

function Set(list)
	local set = {}
	for _, l in ipairs(list) do set[l] = true end
	return set
end

ZRES5 = 4891.97
ZRES6 = 2445.98
ZRES7 = 1222.99
ZRES8 = 611.5

node_keys = { "natural","place","waterway" }

function capitalLevel(capital)
	local capital_al = tonumber(capital) or 0
	if capital == "yes" then
		capital_al = 2
	end
	if capital_al == 0 then
		return nil
	end
	return capital_al
end

function calcRank(place, population, capital_al)
	local rank = 0
	if capital_al and capital_al >= 2 and capital_al <= 4 then
		rank = capital_al
		if population > 3 * 10^6 then
			rank = rank - 2
		elseif population > 1 * 10^6 then
			rank = rank - 1
		elseif population < 100000 then
			rank = rank + 2
		elseif population < 50000 then
			rank = rank + 3
		end
		if place ~= "city" then
			rank = rank + 3
			if place ~= "town" then
				rank = rank + 2
			end
		end
		return rank
	end
	if place ~= "city" and place ~= "town" then
		return nil
	end
	if population > 3 * 10^6 then
		return 1
	elseif population > 1 * 10^6 then
		return 2
	elseif population > 500000 then
		return 3
	elseif population > 200000 then
		return 4
	elseif population > 100000 then
		return 5
	elseif population > 75000 then
		return 6
	elseif population > 50000 then
		return 7
	elseif population > 25000 then
		return 8
	elseif population > 10000 then
		return 9
	end
	return 10
end

function node_function()
	-- Write 'place'
	local place = Find("place")
	if place ~= "" then
		local mz = 13
		local pop = tonumber(Find("population")) or 0
		local capital = capitalLevel(Find("capital"))
		local rank = calcRank(place, pop, capital)

		if     place == "continent"     then mz=0
		elseif place == "country"       then
			if     pop>50000000 then rank=1; mz=1
			elseif pop>20000000 then rank=2; mz=2
			else                     rank=3; mz=3 end
		elseif place == "state"         then mz=4
		elseif place == "province"      then mz=5
		elseif place == "city"          then mz=5
		elseif place == "town" and pop>8000 then mz=7
		elseif place == "town"          then mz=8
		elseif place == "village" and pop>2000 then mz=9
		else return end  -- skip hamlet/neighbourhood/etc at world zoom

		Layer("place", false)
		Attribute("class", place)
		MinZoom(mz)
		if rank then AttributeNumeric("rank", rank) end
		if capital then AttributeNumeric("capital", capital) end
		if place=="country" then
			local iso_a2 = Find("ISO3166-1:alpha2")
			while iso_a2 == "" do
				local rel, role = NextRelation()
				if not rel then break end
				if role == 'label' then
					iso_a2 = FindInRelation("ISO3166-1:alpha2")
				end
			end
			Attribute("iso_a2", iso_a2)
		end
		SetNameAttributes()
		return
	end
end

landcoverKeys = { wood="wood", forest="wood",
                  wetland="wetland",
                  beach="sand", sand="sand", dune="sand",
                  farmland="farmland", farm="farmland", orchard="farmland", vineyard="farmland",
                  glacier="ice", ice_shelf="ice",
                  bare_rock="rock", scree="rock",
                  fell="grass", grassland="grass", grass="grass", heath="grass", meadow="grass",
                  allotments="grass", park="grass", village_green="grass", recreation_ground="grass",
                  scrub="grass", shrubbery="grass", tundra="grass", garden="grass" }

waterwayClasses = Set { "stream", "river", "canal", "drain", "ditch" }
waterClasses    = Set { "river", "riverbank", "stream", "canal", "drain", "ditch", "dock" }

function relation_scan_function()
	if Find("type")=="boundary" and Find("boundary")=="administrative" then
		Accept()
	end
end

function way_function()
	local waterway = Find("waterway")
	local natural  = Find("natural")
	local landuse  = Find("landuse")
	local leisure  = Find("leisure")
	local boundary = Find("boundary")
	local is_closed = IsClosed()

	if Find("disused") == "yes" then return end

	-- Administrative boundaries
	local admin_level = 11
	local isBoundary = false
	while true do
		local rel = NextRelation()
		if not rel then break end
		isBoundary = true
		admin_level = math.min(admin_level, tonumber(FindInRelation("admin_level")) or 11)
	end
	if boundary=="administrative" then
		admin_level = math.min(admin_level, tonumber(Find("admin_level")) or 11)
		isBoundary = true
	end
	if isBoundary and not (Find("maritime")=="yes") then
		local mz = 0
		if     admin_level>=3 and admin_level<5 then mz=4
		elseif admin_level>=5 and admin_level<7 then mz=8
		elseif admin_level==7 then mz=10
		elseif admin_level>=8 then mz=12
		end
		Layer("boundary",false)
		AttributeNumeric("admin_level", admin_level)
		MinZoom(mz)
	end

	-- Waterways
	if waterwayClasses[waterway] and not is_closed then
		if waterway == "river" and Holds("name") then
			Layer("waterway", false)
			Attribute("class", waterway)
			SetNameAttributes()
			SetBrunnelAttributes()
		end
	end

	-- Water polygons
	if natural=="water" or waterClasses[waterway] then
		if Find("covered")=="yes" or not is_closed then return end
		local class="lake"; if waterway~="" then class="river" end
		Layer("water",true)
		SetMinZoomByArea()
		Attribute("class",class)
		return
	end

	-- Landcover
	local l = landuse
	if l=="" then l=natural end
	if l=="" then l=leisure end
	if landcoverKeys[l] then
		Layer("landcover", true)
		SetMinZoomByArea()
		Attribute("class", landcoverKeys[l])
		Attribute("subclass", l)
	end

	-- Parks / nature reserves
	if     boundary=="national_park" then Layer("park",true); Attribute("class",boundary); SetNameAttributes()
	elseif leisure=="nature_reserve" then Layer("park",true); Attribute("class",leisure ); SetNameAttributes() end
end

-- Remap ocean shapefile features
function attribute_function(attr, layer)
	if layer == "ocean" then
		return { class = "ocean" }
	else
		return attr
	end
end

-- ==========================================================
-- Common functions

function SetNameAttributes()
	local name = Find("name")
	local main_written = name
	if preferred_language and Holds("name:"..preferred_language) then
		local iname = Find("name:"..preferred_language)
		Attribute(preferred_language_attribute, iname)
		if iname~=name and default_language_attribute then
			Attribute(default_language_attribute, name)
		else main_written = iname end
	else
		Attribute(preferred_language_attribute, name)
	end
	for i,lang in ipairs(additional_languages) do
		local iname = Find("name:"..lang)
		if iname=="" then iname=name end
		if iname~=main_written then Attribute("name:"..lang, iname) end
	end
end

function SetBrunnelAttributes()
	if Find("bridge") == "yes" or Find("man_made") == "bridge" then Attribute("brunnel", "bridge")
	elseif Find("tunnel") == "yes" then Attribute("brunnel", "tunnel")
	elseif Find("ford")   == "yes" then Attribute("brunnel", "ford")
	end
end

function SetMinZoomByArea()
	SetMinZoomByAreaWithLimit(0)
end

function SetMinZoomByAreaWithLimit(minzoom)
	local area=Area()
	if     minzoom <= 6 and area>ZRES5^2  then MinZoom(6)
	elseif minzoom <= 7 and area>ZRES6^2  then MinZoom(7)
	elseif minzoom <= 8 and area>ZRES7^2  then MinZoom(8)
	elseif minzoom <= 9 and area>ZRES8^2  then MinZoom(9)
	else                      MinZoom(9) end
end

-- vim: tabstop=2 shiftwidth=2 noexpandtab
