require('Module:No globals')
local getArgs = require('Module:Arguments').getArgs

local p = {}

-- Calcola la scala adeguata per mappa OSM
-- esempio chiamata di funzione {{#invoke:Mappa OSM|scala|w|h|x1|y1|x2|y2|...}}
function p.scala(frame)
	local t = getArgs(frame)
	local amn, amx, bmn, bmx = 400, -400, 400, -400
	local dimx = tonumber(t[1]) or 1 --larghezza
	local dimy = tonumber(t[2]) or 1 --altezza
	local vlr
	for i,v in ipairs(t) do 
		if i>2 then
			vlr = tonumber(t[i])
			if (i % 2 == 0) then --calcolo latitudine minima e massima
				if (amn > vlr) then amn = vlr end
				if (amx < vlr) then amx = vlr end
			else --calcolo longitudine minima e massima
				if (bmn > vlr) then bmn = vlr end
				if (bmx < vlr) then bmx = vlr end
			end
		end
	end
	-- per evitare punti troppo vicini al margine
	local dx = 1.1*(bmx-bmn)
	local dy = 1.1*(amx-amn)
	if (dimx>dimy) then
		if (dx<180) then dx = dx*dimy/dimx end
	else
		if (dy<90) then dy = dy*dimx/dimy end
	end
	-- calcolo scale per coordinate
	local scalax, scalay
	if (dx == 0) then scalax = 18 else scalax = math.floor(math.log(360/dx)/math.log(2)) end
	if (dy == 0) then scalay = 18 else scalay = math.floor(math.log(180/dy)/math.log(2)) end
	local scala
    if ((dx == 0) and (dy == 0)) then
    	scala = 10 --valore default per singolo punto
   	else
   		scala = math.max(0,math.min(18,scalax, scalay)) --calcolo scala minima compresa tra 0 e 18
   	end
	return scala
end

-- Calcola la scala adeguata per mappa OSM
-- esempio chiamata di funzione {{#invoke:Mappa OSM|scala|w|h|x1|y1|x2|y2|...}}
function p.scala2(frame)
	local t = getArgs(frame)
	local lat1, lat2, lon1, lon2 = 400, -400, 400, -400
	local dimx = tonumber(t[1]) or 1 --larghezza
	local dimy = tonumber(t[2]) or 1 --altezza
	local vlr
	for i,v in ipairs(t) do 
		if i>2 then
			vlr = tonumber(t[i])
			if (i % 2 == 0) then --calcolo latitudine minima e massima
				if (lat1 > vlr) then lat1 = vlr end
				if (lat2 < vlr) then lat2 = vlr end
			else --calcolo longitudine minima e massima
				if (lon1 > vlr) then lon1 = vlr end
				if (lon2 < vlr) then lon2 = vlr end
			end
		end
	end

	-- problemi con latitudine oltre 85°
	if ((lat2>85) or (lat1<-85)) then return 0 end

	-- calcolo punti proiezione
	local p_lat1 = 128*(1+lat1/180)
	local p_lon1 = 128*(1-math.log(math.tan( math.pi/4 + math.pi*lon1/360)))
	local p_lat2 = 128*(1+lat2/180)
	local p_lon2 = 128*(1-math.log(math.tan( math.pi/4 + math.pi*lon2/360)))

	-- per evitare punti troppo vicini al margine
	local dy = 1.05*(p_lat2-p_lat1)
	local dx = 1.05*(p_lon2-p_lon1)
	if (dimx>dimy) then
		if (dx<180) then dx = dx*dimy/dimx end
	else
		if (dy<90) then dy = dy*dimx/dimy end
	end
	-- calcolo scale per coordinate
	local scalax, scalay
	if (dx == 0) then scalax = 18 else scalax = math.floor(math.log(dimx/dx)/math.log(2)) end
	if (dy == 0) then scalay = 18 else scalay = math.floor(math.log(dimy/dy)/math.log(2)) end
	local scala
    if ((dx == 0) and (dy == 0)) then
    	scala = 10 --valore default per singolo punto
   	else
   		scala = math.max(0,math.min(18,scalax, scalay)) --calcolo scala minima compresa tra 0 e 18
   	end
	return scala
end

-- Calcola centro per singola coordinata
-- esempio chiamata di funzione {{#invoke:Mappa OSM|centro|x1|x2|...}}
function p.centro(frame)
	local t = getArgs(frame)
	local mn, mx = 400, -400
	local xval
	for i,v in ipairs(t) do
		xval = tonumber(t[i])
		if (mn > xval) then mn = xval end
		if (mx < xval) then mx = xval end
	end
    return (mn+mx)/2
end

return p