require("Module:No globals")
local getArgs = require('Module:Arguments').getArgs
local p = {}

local flex = {}
flex['primo'] = {'<div style="display:flex;flex-direction:row;flex-wrap:wrap"><div style="flex-grow:0;flex-shrink:0;flex-basis:auto;padding: 0 2em 0 0">','</div>'}
flex['medio'] = {'<div style="flex-grow:0;flex-shrink:0;flex-basis:auto;padding: 0 2em 0 0">','</div>'}
flex['ultimo'] = {'<div style="flex-grow:0;flex-shrink:0;flex-basis:auto;padding: 0 2em 0 0">','</div></div>'}
flex['destra'] = {'<div class="floatright">','</div>'}

-- =====================================================================
-- Legge gli argomenti per caricare un array di valori numerici.
-- =====================================================================
local function leggi(args, a)
	local array = {}
	if args[a] then
		array = mw.text.split(string.gsub(args[a], "%s", ""), ",")
	end
	for _,v in ipairs(array) do
		v = tonumber(v)
	end
	return array
end
-- =====================================================================
-- Fonde due liste in un'unica lista
-- =====================================================================
local function unisci(a,b,c,d)
	local values = { }
	for i =1,#b do
		values[i] = { nx = a[i]/c, ny = b[i]/d, num = i }
	end
	return values
end

-- =====================================================================
-- Generazione del grafico
-- =====================================================================
function p._grafico(args)
	-- Definizione base del grafico
	local graph = {
		version = 2,
		width = 350,
		height = 250,
		padding = "auto",
		data = {
			{
				name = "tab",
				transform = { { type = "sort", by = "nx" } },
				values = { }
			},
			{
				name = "tab2",
				transform = { { type = "sort", by = "nx" } },
				values = {  }
			},
			{
				name = "tab3",
				transform = { { type = "sort", by = "nx" } },
				values = {  }
			},
			{
				name = "nomi",
				values = { }
			}
		},
		scales = {
			{
				name = "x",
				type = "linear",
				range = "width",
				zero = false,
				___domain = {fields = {{data = "tab",field = "nx"}, {data = "tab2",field = "nx"}, {data = "tab3",field = "nx"}}}
			},
			{
				name = "y",
				type = "linear",
				range = "height",
				zero = true,
				nice = true,
				___domain = {fields = {{data = "tab",field = "ny"}, {data = "tab2",field = "ny"}, {data = "tab3",field = "ny"}}}
			},
			{
				name = "colori",
				type = "ordinal",
				___domain = { data = "nomi", field = "testo"},
				range = { "#1f77b4", "b80000", "#00c000" }
			}
		},
		axes = {
			{
				type = "x",
				scale = "x",
				title = "X",
				format = "d",
				grid = true,
			},
			{
				type = "y",
				scale = "y",
				title = "Y",
				grid = true,
				format = "d",
				layer = "back"
			}
		},
		legends = {
			{
				fill = "colori",
				title = "",
				orient = "top-left",
				offset = 8,
				shape = "square",
				strokeWidth =  0
			}
		},
		marks = {
			{
				type = "line",
				from = {data = "tab" },
				properties = {
					enter = {
						interpolate = {value = "linear"},
						x = {scale = "x",field = "nx"},
						y = {scale = "y",field = "ny"},
						stroke = {value = "#1f77b4"},
						strokeWidth = {value = 4},
						opacity = {value = 0.5}
					}
				}
			},
			{
				type = "line",
				from = {data = "tab2" },
				properties = {
					enter = {
						interpolate = {value = "linear"},
						x = {scale = "x",field = "nx"},
						y = {scale = "y",field = "ny"},
						stroke = {value = "#b80000"},
						strokeWidth = {value = 4},
						opacity = {value = 0.5}
					}
				}
			},
			{
				type = "line",
				from = {data = "tab3" },
				properties = {
					enter = {
						interpolate = {value = "linear"},
						x = {scale = "x",field = "nx"},
						y = {scale = "y",field = "ny"},
						stroke = {value = "#00c000"},
						strokeWidth = {value = 4},
						opacity = {value = 0.5}
					}
				}
			},
			{
				type = "symbol",
				from = {data = "tab"},
				properties = {
					enter = {
						x = {scale = "x",field = "nx"},
						y = {scale = "y",field = "ny"},
						stroke = {value = "1f77b4"},
						fill = {value = "#fff"},
						size = {value = 30}
					}
				}
			},
			{
				type = "symbol",
				from = {data = "tab2"},
				properties = {
					enter = {
						x = {scale = "x",field = "nx"},
						y = {scale = "y",field = "ny"},
						stroke = {value = "#b80000"},
						fill = {value = "#fff"},
						size = {value = 30}
					}
				}
			},
			{
				type = "symbol",
				from = {data = "tab3"},
				properties = {
					enter = {
						x = {scale = "x",field = "nx"},
						y = {scale = "y",field = "ny"},
						stroke = {value = "#00c000"},
						fill = {value = "#fff"},
						size = {value = 30}
					}
				}
			},
			{
				type = "text",
				from = { data = "tab" },
				properties = {
					enter = {
						x = {scale = "x",field = "nx"},
						y = {scale = "y",field = "ny", offset = -6},
						align = {value = "center"},
						fill = {value = "#000"},
						text = {field = "ny" }
					}
				}
			},
			{
				type = "text",
				from = { data = "tab2" },
				properties = {
					enter = {
						x = {scale = "x",field = "nx"},
						y = {scale = "y",field = "ny", offset = -6},
						align = {value = "center"},
						fill = {value = "#000"},
						text = {field = "ny" }
					}
				}
			},
			{
				type = "text",
				from = { data = "tab3" },
				properties = {
					enter = {
						x = {scale = "x",field = "nx"},
						y = {scale = "y",field = "ny", offset = -6},
						align = {value = "center"},
						fill = {value = "#000"},
						text = {field = "ny" }
					}
				}
			}
		}
	}
	-- titoli assi
	local titoloX = args.titoloX or 'X'
	local fattoreX = args.fattoreX and tonumber(args.fattoreX) and tonumber(args.fattoreX) or 1
	if fattoreX == 0 then
		fattoreX = 1
	elseif fattoreX == 1000 then
		titoloX = titoloX..' (migliaia)'
	elseif fattoreX == 1000000 then
		titoloX = titoloX..' (milioni)'
	end
	graph['axes'][1]['title'] = titoloX
	local titoloY = args.titoloY or 'Y'
	local fattoreY = args.fattoreY and tonumber(args.fattoreY) and tonumber(args.fattoreY) or 1
	if fattoreY == 0 then
		fattoreY = 1
	elseif fattoreY == 1000 then
		titoloY = titoloY..' (migliaia)'
	elseif fattoreY == 1000000 then
		titoloY = titoloY..' (milioni)'
	end
	graph['axes'][2]['title'] = titoloY

	-- zero su assi
	if (args.zeroX and args.zeroX == 's') then graph['scales'][1]['zero'] = true end
	if (args.zeroY and args.zeroY == 'n') then graph['scales'][2]['zero'] = false end
	-- legge valori
	local dx1 = leggi(args, "x1")
	local dy1 = leggi(args, "y1")
	local dx2 = leggi(args, "x2")
	local dy2 = leggi(args, "y2")
	local dx3 = leggi(args, "x3")
	local dy3 = leggi(args, "y3")
	graph['data'][1]['values'] =  unisci(dx1, dy1, fattoreX, fattoreY)
	graph['data'][2]['values'] =  unisci(dx2, dy2, fattoreX, fattoreY)
	graph['data'][3]['values'] =  unisci(dx3, dy3, fattoreX, fattoreY)
	-- dimensioni
	graph['width'] = args.dimx and tonumber(args.dimx) and tonumber(args.dimx) or 350
	graph['height'] = args.dimy and tonumber(args.dimy) and tonumber(args.dimy) or 250
	-- colori
	if args.colore1 then
		graph['marks'][1]['properties']['enter']['stroke']['value'] = args.colore1
		graph['marks'][4]['properties']['enter']['stroke']['value'] = args.colore1
		graph['scales'][3]['range'][1] = args.colore1
	end
	if args.colore2 then
		graph['marks'][2]['properties']['enter']['stroke']['value'] = args.colore2
		graph['marks'][5]['properties']['enter']['stroke']['value'] = args.colore2
		graph['scales'][3]['range'][2] = args.colore2
	end
	if args.colore3 then
		graph['marks'][3]['properties']['enter']['stroke']['value'] = args.colore3
		graph['marks'][6]['properties']['enter']['stroke']['value'] = args.colore3
		graph['scales'][3]['range'][3] = args.colore3
	end
	-- opzioni etichette
	if args.etichette1 then
		if args.etichette1 == 'dispari' then
			graph['marks'][7]['from']['transform'] = {{ type = "filter", test = "datum.num % 2 == 1"}}
		elseif args.etichette1 == 'pari' then
			graph['marks'][7]['from']['transform'] = {{ type = "filter", test = "datum.num % 2 == 0"}}
		elseif args.etichette1 == 'no' then
			graph['marks'][7]['from']['transform'] = {{ type = "filter", test = "datum.num < 1"}}
		end
	end
	if args.mostra1 then
		if args.mostra1 == '1' then
			graph['marks'][4]['from']['transform'] = {{ type = "filter", test = "datum.num < 1"}}
		elseif args.mostra1 == '2' then
			graph['marks'][1]['from']['transform'] = {{ type = "filter", test = "datum.num < 1"}}
		end
	end
	if args.etichette2 then
		if args.etichette2 == 'dispari' then
			graph['marks'][8]['from']['transform'] = {{ type = "filter", test = "datum.num % 2 == 1"}}
		elseif args.etichette2 == 'pari' then
			graph['marks'][8]['from']['transform'] = {{ type = "filter", test = "datum.num % 2 == 0"}}
		elseif args.etichette2 == 'no' then
			graph['marks'][8]['from']['transform'] = {{ type = "filter", test = "datum.num < 1"}}
		end
	end
	if args.mostra2 then
		if args.mostra2 == '1' then
			graph['marks'][5]['from']['transform'] = {{ type = "filter", test = "datum.num < 1"}}
		elseif args.mostra2 == '2' then
			graph['marks'][2]['from']['transform'] = {{ type = "filter", test = "datum.num < 1"}}
		end
	end
	if args.etichette3 then
		if args.etichette3 == 'dispari' then
			graph['marks'][9]['from']['transform'] = {{ type = "filter", test = "datum.num % 2 == 1"}}
		elseif args.etichette3 == 'pari' then
			graph['marks'][9]['from']['transform'] = {{ type = "filter", test = "datum.num % 2 == 0"}}
		elseif args.etichette3 == 'no' then
			graph['marks'][9]['from']['transform'] = {{ type = "filter", test = "datum.num < 1"}}
		end
	end
	if args.mostra3 then
		if args.mostra3 == '1' then
			graph['marks'][6]['from']['transform'] = {{ type = "filter", test = "datum.num < 1"}}
		elseif args.mostra3 == '2' then
			graph['marks'][3]['from']['transform'] = {{ type = "filter", test = "datum.num < 1"}}
		end
	end
	-- legenda
	if args.nome1 then graph['data'][4]['values'][1] = { testo = args.nome1 } end
	if args.nome2 then graph['data'][4]['values'][2] = { testo = args.nome2 } end
	if args.nome3 then graph['data'][4]['values'][3] = { testo = args.nome3 } end
	if args.legenda then graph['legends'][1]['orient'] = args.legenda end

	local ris = {}
	local allinea = args['allinea'] or ''
	if (flex[allinea]) then table.insert(ris,flex[allinea][1]) end
	table.insert(ris,mw.getCurrentFrame():extensionTag('graph', mw.text.jsonEncode(graph)))
	if (args.didascalia) then
		table.insert(ris,'<p>'..args.didascalia..'</p>')
	end
	if (flex[allinea]) then table.insert(ris,flex[allinea][2]) end
	return table.concat(ris)
end

-- ======================================================================================================
-- Funzione di intefaccia con template:Demografia
-- ======================================================================================================
function p.grafico(frame)
	local args = getArgs(frame)
	return p._grafico(args)
end

return p