--[[
	mtv.ch
	Copyright (C) 2015,2019,2020  Jacek Jendrzej 'satbaby'
	With Help from: Thomas(2015,2016,2017,2018,2019,2020),Dosik7(2017),BPanther(2018)

	License: GPL

	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public
	License as published by the Free Software Foundation; either
	version 2 of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
	General Public License for more details.

	You should have received a copy of the GNU General Public
	License along with this program; if not, write to the
	Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
	Boston, MA  02110-1301, USA.
]]

local glob = {}
local mtv_version="mtv.de Version 0.37" -- Lua API Version: " .. APIVERSION.MAJOR .. "." .. APIVERSION.MINOR
local n = neutrino()
local conf = {}
local on="ein"
local off="aus"

function get_confFile()
	return "/var/tuxbox/config/mtv.conf"
end
function get_conf_mtvfavFile()
	return "/var/tuxbox/config/mtvfav.conf"
end

function hideMenu(menu)
	if menu ~= nil then menu:hide() end
end

function setvar(k, v)
	if v and #v > 0 then
		conf[k]=v
		conf.changed = true
	end
end

function file_exists(file)
	local fh = filehelpers.new()
	if fh then return fh:exist(file, "f") else return false end
end

function saveConfig()
	if conf.changed then
		local config	= configfile.new()
		config:setString("path", conf.path)
		config:setString("path_m3u", conf.path_m3u)
		config:setBool  ("dlflag",conf.dlflag)
		config:setBool  ("flvflag",conf.flvflag)
		config:setBool  ("hlsflag",conf.hlsflag)
		config:setBool  ("playflvflag",conf.playflvflag)
		config:setBool  ("shuffleflag",conf.shuffleflag)
		config:setString("maxRes", conf.maxRes)
		config:setString("search", conf.search)
		config:saveConfig(get_confFile())
		conf.changed = false
	end
	if glob.fav_changed == true then
		local file_mtvconf=io.open(get_conf_mtvfavFile(),"w")
		for k, v in ipairs(glob.mtv) do
			if v.fav == true then
				file_mtvconf:write('name="'.. v.name ..'",url="'.. v.url ..'"\n')
			end
		end
		file_mtvconf:close()
	end
end

function loadConfig()
	local config	= configfile.new()
	config:loadConfig(get_confFile())
	conf.path = config:getString("path", "/media/sda1/movies/")
	conf.path_m3u = config:getString("path_m3u", "/media/sda1/movies/")
	conf.dlflag = config:getBool("dlflag", false)
	conf.flvflag = config:getBool("flvflag", false)
	conf.hlsflag = config:getBool("hlsflag", true) --hls as default, rtmp server is broken???
	conf.playflvflag = config:getBool("playflvflag", false)
	conf.shuffleflag = config:getBool("shuffleflag", false)
	conf.maxRes = config:getString("maxRes", "1280x720")
	conf.search = config:getString("search", "Justin Bieber")
	conf.changed = false
end

function which(bin_name)
	local path = os.getenv("PATH") or "/bin"
	for v in path:gmatch("([^:]+):?") do
		local file = v .. "/" .. bin_name
		if file_exists(file) then
			return true
		end
	end
	return false
end

function read_file(filename)
	if filename == nil then
		print("Error: FileName  is empty")
		return nil
	end
	local fp = io.open(filename, "r")
	if fp == nil then print("Error opening file '" .. filename .. "'.") return nil end
	local data = fp:read("*a")
	fp:close()
	return data
end
function get_json_data(url)
	local data = getdata(url)
	if data == nil then return nil end
	local videosection = string.match(data,"triforceManifestFeed = (.-});")
	if glob.mtv_live_url == nil then
		glob.mtv_live_url = data:match("(http[%w%./:]+mtv%-germany%-live)")
	end
	data = nil
	collectgarbage()
	return videosection
end

function init()
	collectgarbage()
	if vodeoPlay == nil then
		vodeoPlay = video.new()
	end

	glob.fav_changed = false
	glob.mtv_artist={}
	glob.mtv={
			{name = "Playlists",url="http://www.mtv.de/playlists",fav=false},
			{name = "MTV MUSIK",url="http://www.mtv.de/musik",fav=false},
			{name = "MTV Unplugged",url="http://www.mtv.de/shows/w2nofb/mtv-unplugged",fav=false},
			{name = "Hitlist Germany - Top100",url="http://www.mtv.de/shows/fdc2nt/mtv-top-100",fav=false},
			{name = "MTV Shows",url="http://www.mtv.de/shows",fav=false},
			{name = "MTV Buzz",url="http://www.mtv.de/buzz",fav=false},
			--{name = "MTV PUSH",url="http://www.mtv.de/shows/z4pet5/mtv-push",fav=false},
			{name = "MTV PLAYLIST",url="http://www.mtv.de/playlists",fav=false},
			{name = "ALLE MUSIKVIDEOS",url="http://www.mtv.de/musik",fav=false},
			{name = "Singel Top 100",url="http://www.mtv.de/charts/c6mc86/single-top-100",fav=false},
			--{name = "Album Top 100",url="http://www.mtv.de/charts/70tgrf/album-top-100",fav=false},
			{name = "Midweek Singel Top100",url="http://www.mtv.de/charts/n91ory/midweek-single-top-100",fav=false},
			--{name = "Midweek Album Top100",url="http://www.mtv.de/charts/ew735d/midweek-album-top-100",fav=false},
			{name = "Singel Trending",url="http://www.mtv.de/charts/9gtiy5/single-trending",fav=false},
			{name = "Top100 Musik Streaming",url="http://www.mtv.de/charts/h4oi23/top100-music-streaming",fav=false},
			{name = "Download Charts Singel",url="http://www.mtv.de/charts/pcbqpc/downloads-charts-single",fav=false},
			--{name = "Download Charts Album",url="http://www.mtv.de/charts/ha7dbg/downloads-charts-album",fav=false},
			{name = "Top15 deutsche Singel",url="http://www.mtv.de/charts/jlyhaa/top-15-deutschsprachige-single-charts",fav=false},
			--{name = "Top15 deutsche Alben",url="http://www.mtv.de/charts/wp4sh5/top-15-deutschsprachige-alben-charts",fav=false},
			--{name = "Hip Hop",url="http://www.mtv.de/charts/vh9pco/hip-hop-charts",fav=false},
			{name = "Dance Charts",url="http://www.mtv.de/charts/2ny5w9/dance-charts",fav=false},
	}

	local url = "http://www.mtv.de/charts"
	glob.mtv_live_url = nil
	videosection = get_json_data(url)
	if videosection == nil then return nil end

	local json = require "json"
	local jnTab = json:decode(videosection)
	if jnTab == nil  then return nil end
	local videosection_url = jnTab.manifest.zones.t5_lc_promo1.feed
	videosection = getdata(videosection_url)
	if videosection == nil then return nil end
	jnTab = json:decode(videosection)
	local pages = 1
	videosection_url = videosection_url:match("(.*)%d+$")

	local add = true
	local add2016 = false
	if jnTab.result and jnTab.result.chartTypeList then
		for k, v in ipairs(jnTab.result.chartTypeList) do
			if v.label and v.link then
				if v.label:find("Offizielle") == nil and v.label ~= "Deine Lieblingsvideos bei MTV" and v.label:find("Album") == nil and v.label:find("Alben") == nil and v.label:find("Vinyl") == nil then
					table.insert(glob.mtv,{name=v.label, url=v.link,})
					if add2016 == false and v.label == "Top 100 Jahrescharts 2015" then
						add2016 = true
						table.insert(glob.mtv,{name="Top 100 Jahrescharts 2016", url="http://www.mtv.de/charts/yrk67s/top-100-jahrescharts-2016",})
					end
				end
			end
		end
	end
	local mtvconf = get_conf_mtvfavFile()
	local havefile = file_exists(mtvconf)
	if havefile == true then
		local favdata = read_file(mtvconf)
		if havefile ~= nil then
			for _name ,_url in favdata:gmatch('name%s-=%s-"(.-)"%s-,%s-url%s-=%s-"(.-)"') do
				table.insert(glob.mtv,{name=_name, url=_url,fav=true})
			end
		end
	end
end

function info(captxt,infotxt, sleep)
	if captxt == mtv_version and infotxt==nil then
		infotxt=captxt
		captxt="Information"
	end
	local msg, data = 0,0
	local h = hintbox.new{caption=captxt, text=infotxt}
	h:paint()
	if sleep then
		for i=1,sleep*5,1 do
			msg, data = n:GetInput(500)
			if msg == RC.ok or msg == RC.home then
				break
			end
		end
	else
		repeat
			msg, data = n:GetInput(500)
		until msg == RC.ok or msg == RC.home
	end
	h:hide()
end

function getdata(Url,outputfile)
	if Url == nil then return nil end
	if Curl == nil then
		Curl = curl.new()
	end
	local ret, data = Curl:download{url=Url,A="Mozilla/5.0;",maxRedirs=5,followRedir=true,o=outputfile }
	if ret == CURL.OK then
		if outputfile then
			return 1
		end
		return data
	else
		return nil
	end
end

function exist_url(tab,_url)
	for i, v in ipairs(tab) do
		if v.url == _url then
			return true
		end
	end
	return false
end

function getliste(url)
	local h = hintbox.new{caption="Info", text="Liste wird erstellt\n"}
	h:paint()

	local videosection = get_json_data(url)
	if videosection == nil then h:hide() return nil end

	local liste = {}
	local json = require "json"
	local urlTab = json:decode(videosection)
	local tc = {"t4_lc_promo1"}
	if url == "http://www.mtv.de/musik" then tc = {"t4_lc_promo1","t5_lc_promo1","t6_lc_promo1","t7_lc_promo1","t8_lc_promo1","t9_lc_promo1","t10_lc_promo1","t11_lc_promo1"}  end
	for t in pairs(tc) do
		if urlTab.manifest.zones[tc[t]] and urlTab.manifest.zones[tc[t]].feed then
			local videosection_url = urlTab.manifest.zones[tc[t]].feed
			for p=1,6,1 do
				if videosection_url then
					local  pc = "?"
					if videosection_url:find("?") then pc = "&" end
					videosection = getdata(videosection_url .. pc .. "pageNumber=" .. p)
					if videosection == nil then
						if #liste > 0 then h:hide() return liste else return nil end
					end
				else
					h:hide()
					return nil
				end

				local jnTab = json:decode(videosection)
				if jnTab == nil or jnTab.result == nil or jnTab.result.data == nil then h:hide()  if #liste > 0 then return liste else return nil end end
				for k, v in ipairs(jnTab.result.data.items) do
					if v.videoUrl or v.canonicalURL then
						local video_url = v.videoUrl or v.canonicalURL
							if exist_url(liste,video_url) == false then
							local artist = v.shortTitle or v.artist or ""
							if #artist == 0 and v.artists then artist = v.artists[1].name end
							local _logo = nil
							if v.images and v.images.url then _logo = v.images.url end
							_logo = _logo or ""
							local chpos = nil
							if v.chartPosition and v.chartPosition.current then chpos = v.chartPosition.current end
							table.insert(liste,{name=artist .. ": " .. v.title, url=video_url,
							logo=_logo,enabled=conf.dlflag, vid=id,chartpos=chpos
							})
						end
					end
				end
			end
		end
	end
	h:hide()
	return liste
end
function get_m3u_url(m3u8_url)
	if m3u8_url == nil then return nil end
	local videoUrl = nil
	local res = 0
	local data = getdata(m3u8_url)
	if data then
		local host = m3u8_url:match('([%a]+[:]?//[_%w%-%.]+)/')
		if m3u8_url:find('/master.m3u8') then
			local lastpos = (m3u8_url:reverse()):find("/")
			local hosttmp = m3u8_url:sub(1,#m3u8_url-lastpos)
			if hosttmp then
				host = hosttmp .."/"
			end
		end
		local maxRes = 1280
		if conf.maxRes then
			local maxResStr = conf.maxRes:match("(%d+)x")
			maxRes = tonumber(maxResStr)
		end
		for band, res1, res2, url in data:gmatch('BANDWIDTH=(%d+).-RESOLUTION=(%d+)x(%d+).-\n(.-)\n') do
			if url and res1 then
				local nr = tonumber(res1)
				if nr <= maxRes and nr > res then
					res=nr
					if host and url:sub(1,4) ~= "http" then
						url = host .. url
					end
					videoUrl = url
				end
			end
		end
	end
	return videoUrl
end

function getvideourl(url,vidname,hls)
	local	json = require "json"
	local data = getdata(url)
	local id = data:match('itemId":"(.-)"')
	local service_url = "http://media.mtvnservices.com/pmt/e1/access/index.html?uri=mgid:arc:episode:mtv.de:" .. id .. "&configtype=edge&ref=" .. url
	data = getdata(service_url)
	local jnTab = json:decode(data)
	if jnTab.feed.items[1].group.content then
		local jsUrl = jnTab.feed.items[1].group.content
		if hls then
			jsUrl = jsUrl:gsub("(&device=.-)&","")
			jsUrl = jsUrl .. "&acceptMethods=hls"
		end
		data = getdata(jsUrl .. "&format=json")
		if data then
			jnTab = json:decode(data)
		end
	end
	data = nil

	local max_w = 0
	local video_url = nil
	if jnTab and jnTab.package and jnTab.package.video and jnTab.package.video.item and jnTab.package.video.item[1].rendition then
		for k,v in pairs(jnTab.package.video.item[1].rendition) do
			if (hls or v.width or v.rdminwidth) and v.src then
				local w = tonumber(v.width or v.rdminwidth)
				if hls or w > max_w then
					video_url = v.src
					max_w = w
				end
			end
		end
	end
	local x = nil
	if video_url then
		if video_url:find("m3u8") then
			video_url = get_m3u_url(video_url)
		end
		x = video_url:find("rtmp") or video_url:find("m3u8")
	end
	if not x then
	  print("########## Error ##########")
	  print(url,video_url,clip_page)
	  print("###########################")
	end
	if video_url and video_url:find("copyright_error") then
		if h then
			h:hide()
		end
		info("Video Not Available", "Copyright Error\n" .. vidname,2)
	end
	return video_url
end

function godirectkey(d)
	if d  == nil then return d end
	local  _dkey = ""
	if d == 1 then
		_dkey = RC["red"]
	elseif d == 2 then
		_dkey = RC["green"]
	elseif d == 3 then
		_dkey = RC["yellow"]
	elseif d == 4 then
		_dkey = RC["blue"]
	elseif d < 14 then
		_dkey = RC[""..d - 4 ..""]
	elseif d == 14 then
		_dkey = RC["0"]
	else
		-- rest
		_dkey = ""
	end
	return _dkey
end

function action_exec(id)
	if id  then
		local i = tonumber(id)
		if glob.MTVliste[i].name == nil then
			glob.MTVliste[i].name = "NoName_" .. i
		end
		local url = getvideourl(glob.MTVliste[i].url,glob.MTVliste[i].name,conf.hlsflag)
		if url then
			hideMenu(glob.menu_liste)
			vodeoPlay:setSinglePlay()
			vodeoPlay:PlayFile(glob.MTVliste[i].name, url);
		end
	end
	return MENU_RETURN.EXIT_REPAINT
end

function gen_m3u_list(filename)
	local m3ufilename= conf.path_m3u .. "/" .. filename .. ".m3u"

	local m3ufile=io.open(m3ufilename,"w")
	if m3ufile then
		m3ufile:write("#EXTM3U name=" .. filename .. "\n")
		local infotext = "Dateien werden für M3U Liste vorbereitet.  "
		local pw = cprogresswindow.new{title=infotext}
		pw:paint()
		pw:showStatus{statusText="Start"}
        for k, v in ipairs(glob.MTVliste) do
			if v.name == nil then
				v.name = "NoName"
			end
			local url = getvideourl(v.url,v.name,conf.hlsflag)
			if url then
				local extinf = ", "
				if v.logo and #v.logo > 1 then --TODO Add Logo parse to CMoviePlayerGui::parsePlaylist
					extinf = " logo=" .. v.logo ..".jpg ,"
				end
				extinf = extinf .. v.name
				m3ufile:write("#EXTINF:-1".. extinf .."\n")
				m3ufile:write(url .."\n")
				pw:showStatus{prog=k,max=#glob.MTVliste,statusText=tostring(k) .. "/" .. tostring(#glob.MTVliste) .. "  " .. v.name}
			end
		end
		m3ufile:close()
		pw:hide()
		info("Info", filename.." - Playlist wurde erstellt\n" .. m3ufilename,2)
	else
		info("Info", filename.." - Fehler beim erstellen:\n " .. m3ufilename .. " ",3)
	end
	return MENU_RETURN.EXIT_REPAINT
end

function make_shuffle_list(tab)
	local randTable={}
	for k=1 , #tab do
		randTable[k]=k
	end
	local shuffleTable = {}
	for k=1,#randTable do
		math.randomseed(os.time() *100000000000)
		local r=table.remove(randTable,math.random(#randTable))
		shuffleTable[k]=tab[r]
	end
	return shuffleTable
end

function playlist(filename)
	hideMenu(glob.menu_liste)

	local tab = {}
	if conf.shuffleflag == true then
		tab = make_shuffle_list(glob.MTVliste)
	else
		tab = glob.MTVliste
	end

	local i = 1
	local KeyPressed = 0
	vodeoPlay:setSinglePlay(false)
	repeat
		if tab[i].name == nil then
			tab[i].name = "NoName"
		end
		local url = getvideourl(tab[i].url,tab[i].name,conf.hlsflag)
		if url then
			local videoformat = url:sub(-4)
			if videoformat ~= ".flv" or conf.playflvflag then
				local prevn , nextn = "",""
				if i-1 ~= 0 then
					prevn = "Vorherige Titel: " .. tab[i-1].name
				end
				if i < #tab then
					nextn = "Nächste Titel: ".. tab[i+1].name
				end
				KeyPressed = vodeoPlay:PlayFile( "(" .. i.. "/" .. #tab .. ") " .. tab[i].name,url, nextn, prevn)
			end
		end
		if KeyPressed == PLAYSTATE.NORMAL then --play continue
			i=i+1
		elseif KeyPressed == PLAYSTATE.STOP then
			i=0
			break
		elseif KeyPressed == PLAYSTATE.NEXT then
			i=i+1
		elseif KeyPressed == PLAYSTATE.PREV then
			i=i-1
		else
			print("Error")
			i=0
			break
		end

	until i==0 or i == #tab+1

	return MENU_RETURN.EXIT_REPAINT
end

function dlstart(name)
	local infotext = "Dateien werden für Download vorbereitet.  "
	name = name:gsub([[%s+]], "_")
	name = name:gsub("[:'&()/]", "_")
	local dlname = "/tmp/" .. name ..".dl"
	local havefile = file_exists("/tmp/.rtmpdl")
	if havefile == true then
		info("Info", "Ein anderer Download ist bereits aktiv.",4)
		return
	end
	local dl=io.open(dlname,"w")
	local script_start = false

	local pw = cprogresswindow.new{title=infotext}
	pw:paint()
	pw:showStatus{statusText="Start"}
	for i, v in ipairs(glob.MTVliste) do
		if v.enabled == true then
			if glob.MTVliste[i].name == nil then
				glob.MTVliste[i].name = "NoName_" .. i
			end
			local url = getvideourl(glob.MTVliste[i].url,glob.MTVliste[i].name,conf.hlsflag)
			if url then
				local fname = v.name:gsub([[%s+]], "_")
				fname = fname:gsub("[:'()]", "_")
				fname = fname:gsub("/", "-")
				pw:showStatus{prog=i,max=#glob.MTVliste,statusText=tostring(i) .. "/" .. tostring(#glob.MTVliste) .. "  " .. fname}
				local videoformat = url:sub(-4)
				if videoformat == nil then
					videoformat = ".mp4"
				end
				if conf.hlsflag then
					dl:write("ffmpeg -y -nostdin -loglevel 30 -i " .. url .. " -c copy  " .. conf.path .. "/" .. fname   .. ".ts\n")
					script_start = true
				elseif videoformat ~= ".flv" or conf.flvflag then
					dl:write("rtmpdump -e -r " .. url .. " -o " .. conf.path .. "/" .. fname  .. videoformat .."\n")
					script_start = true
				end
			end
		end
	end
	pw:hide()
	if script_start == true then
	dl:close()
	local scriptname  = "/tmp/" .. name ..".sh"
	local script=io.open(scriptname,"w")
	script:write(
	[[#!/bin/sh
	while read -r i
	do
		$i
	done < ]]
	)
	script:write("'" .. dlname .. "'\n")
	script:write([[
	wget -q 'http://127.0.0.1/control/message?popup=Video Liste ]])
		script:write(name .. " wurde heruntergeladen.' -O /dev/null\n")
		script:write("rm '" .. dlname .. "'\n")
		script:write("rm '" .. scriptname .. "'\n")
		script:write("rm /tmp/.rtmpdl\n")

		script:close()
		os.execute("echo >/tmp/.rtmpdl")
		os.execute("sleep 2")
		os.execute("chmod 755 '" .. scriptname .. "'")
		os.execute("sh '"..scriptname.."' &")
	else
		local er = hintbox.new{caption="Info", text=name .." - \nDownload ist fehlerhaft \noder Video in FLV-Format"}
		er:paint()
		os.remove(dlname)
		print("ERROR")
		os.execute("sleep 2")
		er:hide()
	end
end

function exist(_url)
	for i, v in ipairs(glob.mtv) do
		if v.fav == true and v.url == _url then
			return true
		end
	end
	return false
end

function addfav(id)
	local addinfo = false
	for i, v in ipairs(glob.mtv_artist) do
		if v.enabled and exist(v.url) == false then
			table.insert(glob.mtv,{name=v.name, url=v.url,fav=true})
			glob.mtv_artist[i].disabled=true
			glob.fav_changed = true
			addinfo = true
		end
	end
	if addinfo == true then
		info("Info","Zu Favoriten hinzugefügt",2)
	end
end

function favdel(id)
	local delinfo = false
	for i, v in ipairs(glob.mtv) do
		if v.fav and v.enabled then
			table.remove(glob.mtv,i)
			glob.fav_changed = true
			delinfo = true
		end
	end
	if delinfo == true then
		info("Info","Ausgewählten Favoriten gelöscht",2)
	end

end

function chooser_menu(id)
	if id:sub(1,29) =="Erstelle Download Liste für " then
		local forwarder_action = "dlstart"
		local forwarder_name = "Download starten"
		local chooser_action = "set_bool_in_liste"
		local hintname = "Speichert die ausgewählten Videos unter: " .. conf.path
		local _id = id:sub(30,#id)
		local name = id
		local value=conf.dlflag
		gen_chooser_menu(glob.MTVliste, name, _id, chooser_action, forwarder_action, forwarder_name, hintname, value, glob.menu_liste)
	elseif id:sub(1,15) =="Neue Favoriten" then
		local forwarder_action = "addfav"
		local forwarder_name = "Zu Favoriten hinzufügen"
		local chooser_action = "set_bool_in_searchliste"
		local hintname = "Speichert die ausgewählten Videos unter: " .. conf.path
		local name = id .. " hinzufügen"
		local value=false
		gen_chooser_menu(glob.mtv_artist, name , id, chooser_action, forwarder_action, forwarder_name, hintname, value, glob.search_artists_menu)
	elseif id =="favdel" then
		local forwarder_action = "favdel"
		local forwarder_name = "Favoriten löschen"
		local chooser_action = "set_bool_in_mtv"
		local hintname = "Lösche die ausgewählten Videos."
		local name = id .. " hinzufügen"
		local value=false
		gen_chooser_menu(glob.mtv, name , id, chooser_action, forwarder_action, forwarder_name, hintname, value, glob.settings_menu)

	end
end

function set_bool_in_liste(k, v)
	local i = tonumber(k)
	if v == on then
		glob.MTVliste[i].enabled=true
	else
		glob.MTVliste[i].enabled=false
	end
end

function set_bool_in_searchliste(k, v)
	local i = tonumber(k)
	if v == on then
		glob.mtv_artist[i].enabled=true
	else
		glob.mtv_artist[i].enabled=false
	end
end

function set_bool_in_mtv(k, v)
	local i = tonumber(k)
	if v == on then
		glob.mtv[i].enabled=true
	else
		glob.mtv[i].enabled=false
	end
end

function gen_chooser_menu(table, name , _id, _chooser_action, _forwarder_action, _forwarder, _hintname, _value, hidemenu)
	hideMenu(hidemenu)
	local menu =  menu.new{name=name, icon="icon_red"}
	menu:addItem{type="back"}
	menu:addItem{type="separatorline"}
	local d = 1 -- directkey

	menu:addItem{type="forwarder", name=_forwarder, action=_forwarder_action, enabled=true,
	id=_id, directkey=godirectkey(d),hint=_hintname}
	menu:addItem{type="separatorline"}
	for i, v in ipairs(table) do
		if (("favdel" == _forwarder_action and v.fav==true) or "addfav" ==  _forwarder_action or "dlstart" ==  _forwarder_action) then
			d = d + 1
			local dkey = godirectkey(d)
			menu:addItem{type="chooser", action=_chooser_action, options={ on, off }, id=i, value=bool2onoff(_value), 
			name= i .. ": " ..v.name, hint_icon="hint_service",hint=v.name .. " speichern ? Ein/Aus"}
		end
	end
	menu:exec()
	menu:hide()
	return MENU_RETURN.EXIT_REPAINT
end

function __menu(_menu,menu_name,table,_action)
	if table == nil or #table == 0 then
		info("Info", "Liste ist leer.", 1)
		return
	end
	hideMenu(glob.mtv_listen_menu)
	_menu:addItem{type="back"}
	_menu:addItem{type="separatorline"}
	local d = 1 -- directkey
	local playhint = "Playlist: "
	if conf.shuffleflag then
		playhint = "Playlist in zufällig Reihenfolge: "
	end
	_menu:addItem{type="forwarder", name="Playlist", action="playlist", enabled=true,
	id="Playlist " .. menu_name, directkey=godirectkey(d),hint=playhint .. menu_name}
        d=d+1
	_menu:addItem{type="forwarder", name="Erstelle M3U Playlist", action="gen_m3u_list", enabled=true,
	id=menu_name, directkey=godirectkey(d),hint="Erstelle eine M3U Playlist im Verzeichnis: " .. conf.path_m3u .. "/" .. menu_name .. ".m3u"}
	d = d + 1
	_menu:addItem{type="forwarder", name="Erstelle Download Liste", action="chooser_menu", enabled=glob.have_rtmpdump,
			id="Erstelle Download Liste für "..menu_name, directkey=godirectkey(d),hint="Welche Videos sollen heruntergeladen werden ?"}
	_menu:addItem{type="separatorline"}
	d = d + 1 --skip blue

	for i, v in ipairs(table) do
		d = d + 1
		local dkey = godirectkey(d)
		local cont = i .. ": "
		if v.chartpos then
			cont = " (" .. v.chartpos .. ") "
		end
		_menu:addItem{type="forwarder", name=cont .. v.name, action=_action,enabled=true,id=i,directkey=dkey,hint=""}
	end
	_menu:exec()
	_menu:hide()
	return MENU_RETURN.EXIT_REPAINT
end

function mtv_liste(id)
	local i = tonumber(id)
	glob.MTVliste=nil;
	local url=glob.mtv[i].url
	glob.MTVliste = getliste(url)
	glob.menu_liste  = menu.new{name=glob.mtv[i].name, icon="icon_blue"}
	__menu(glob.menu_liste ,glob.mtv[i].name, glob.MTVliste,"action_exec")
	collectgarbage()
	return MENU_RETURN.EXIT_REPAINT
end

function set_path(id,value)
	if conf[id] ~= value then
		conf[id]=value
		conf.changed = true
	end
end

function set_option(k, v)
	if k == "maxRes" then
		conf[k]=v
	end

	if v == on then
		conf[k]=true
	elseif v == off then
		conf[k]=false
	end
	if k == "hlsflag" then
		glob.have_rtmpdump=nil
		if conf[k] then
			glob.have_rtmpdump=which("ffmpeg")
		else
			glob.have_rtmpdump=which("rtmpdump")
		end
	end
	conf.changed = true
end

function bool2onoff(a)
	if a then return on end
	return off
end

function setings()
	hideMenu(glob.main_menu)

	local d =  1
	local menu =  menu.new{name="Einstellungen", icon="icon_blue"}
	glob.settings_menu = menu
	menu:addItem{type="back"}
	menu:addItem{type="separatorline"}
	menu:addItem{ type="filebrowser", dir_mode="1", id="path", name="Verzeichnis: ", action="set_path",
		   enabled=true,value=conf.path,directkey=godirectkey(d),
		   hint_icon="hint_service",hint="In welchem Verzeichnis soll das Video gespeichert werden ?"
		 }
	d=d+1
	menu:addItem{ type="filebrowser", dir_mode="1", id="path_m3u", name="Verzeichnis M3U: ", action="set_path",
		   enabled=true,value=conf.path_m3u,directkey=godirectkey(d),
		   hint_icon="hint_service",hint="In welchem Verzeichnis soll das M3U Playlist gespeichert werden ?"
		 }
	d=d+1
	menu:addItem{type="chooser", action="set_option", options={ on, off }, id="hlsflag", value=bool2onoff(conf.hlsflag), directkey=godirectkey(d), name="Videos in HLS-Format",hint_icon="hint_service",hint="HLS als bevorzugte Video Format 'ein' oder 'aus'"}
	d=d+1
	local res_opt={ '3840x2160','2560x1440','1920x1080','1280x720','854x480','640x360' }
	menu:addItem{type="chooser", action="set_option", options=res_opt, id="maxRes", value=conf.maxRes, name="Max. Auflösung" ,directkey=godirectkey(d),hint_icon="hint_service",hint="Max. Video Auflösung"}
	d=d+1
	menu:addItem{type="chooser", action="set_option", options={ on, off }, id="dlflag", value=bool2onoff(conf.dlflag), directkey=godirectkey(d), name="Auswahl vorbelegen mit",hint_icon="hint_service",hint="Erstelle Auswahlliste mit 'ein' oder 'aus'"}
	d=d+1
	menu:addItem{type="chooser", action="set_option", options={ on, off }, id="flvflag", value=bool2onoff(conf.flvflag), directkey=godirectkey(d), name="Videos in FLV-Format herunterladen ? ",hint_icon="hint_service",hint="Videos in FLV-Format sind meisten mit nicht kompatiblen Video-Codec (zB: vp6f)."}
	d=d+1
	menu:addItem{type="chooser", action="set_option", options={ on, off }, id="playflvflag", value=bool2onoff(conf.playflvflag),
	directkey=godirectkey(d), name="Videos in FLV-Format abspielen ? ",hint_icon="hint_service",hint="Videos in FLV-Format sind meisten mit nicht kompatiblen Video-Codec (zB: vp6f)."}
	d=d+1
	menu:addItem{type="chooser", action="set_option", options={ on, off }, id="shuffleflag", value=bool2onoff(conf.shuffleflag),
	directkey=godirectkey(d), name="Zufällig abspielen ? ",hint_icon="hint_service",hint="Video wiedergabelisten zufällig abspielen. "}

	menu:addItem{type="separatorline"}
	d=d+1
	menu:addItem{type="forwarder", name="Ausgewählte Favoriten löschen.", action="chooser_menu", enabled=true,
	id="favdel", directkey=godirectkey(d),hint="Favoriten bearbeiten"}
	menu:exec()
	menu:hide()
	return MENU_RETURN.EXIT_REPAINT
end

function gen_search_list(search)
	local url = "http://www.mtv.de/kuenstler/" .. search:sub(1,1) .. "/1"
	glob.mtv_artist = {}
	local videosection = get_json_data(url)
	if videosection == nil then return nil end

	data = nil
	collectgarbage()

	if videosection == nil then return nil end

	local json = require "json"
	local jnTab = json:decode(videosection)
	if jnTab == nil  then return nil end
	local videosection_url = jnTab.manifest.zones.t5_lc_promo1.feed
	videosection = getdata(videosection_url)
	if videosection == nil then return nil end

	jnTab = json:decode(videosection)
	local pages = 1
	videosection_url = videosection_url:match("(.*)%d+$")
	if jnTab.result.pages then pages = tonumber(jnTab.result.pages) end

	for p=1,pages,1 do
		if p > 1 then
			if videosection_url then
				videosection = getdata(videosection_url .. p)
				if videosection == nil then
					return MENU_RETURN.EXIT_REPAINT
				end
			else
				return MENU_RETURN.EXIT_REPAINT
			end
			jnTab = json:decode(videosection)
		end

		if jnTab == nil or jnTab.result == nil or jnTab.result.artists == nil then return MENU_RETURN.EXIT_REPAINT end

		local add = true
		local use_seek = #search > 1
		for k, v in ipairs(jnTab.result.artists) do
			if v.name and v.canonicalURL then
				if use_seek then
					local name = v.name:lower()
					local a,b = name:find(search:lower())
					if a == 1 and b then add = true else add = false end
				end
				if add then
					table.insert(glob.mtv_artist,{name=v.name, url=v.canonicalURL, enabled=false,disabled=false})
				end
			end
		end
	end

	return MENU_RETURN.EXIT_REPAINT

end

function searchliste(id)
	hideMenu(glob.artists_menu)
	local i = tonumber(id)
	glob.MTVliste=nil;
	if glob.mtv_artist[i].disabled == true then return end
	local url=glob.mtv_artist[i].url
	glob.MTVliste = getliste(url)
	glob.menu_liste  = menu.new{name=glob.mtv_artist[i].name, icon="icon_blue"}
	__menu(glob.menu_liste ,glob.mtv_artist[i].name, glob.MTVliste,"action_exec")
	collectgarbage()
	return MENU_RETURN.EXIT_REPAINT
end

function search_artists()
	if conf.search == nil then return end

	hideMenu(glob.main_menu)
	local h = hintbox.new{caption="Info", text="Suche: " .. conf.search}
	h:paint()
	if #conf.search > 0 then
		gen_search_list(conf.search)
	end
	h:hide()
	if glob.mtv_artist == nil or #glob.mtv_artist == 0 then
		info("Info", "Liste ist leer.", 1)
		return
	end

	local d = 1
	local menu =  menu.new{name=conf.search, icon="icon_yellow"}
	glob.search_artists_menu = menu
	glob.artists_menu = menu
	menu:addItem{type="back"}
	menu:addItem{type="separatorline"}
	menu:addItem{type="forwarder", name="Neue Favoriten hinzufügen", action="chooser_menu", enabled=true,
	id="Neue Favoriten", directkey=godirectkey(d),hint="Listen für Favoriten auswählen und hinzufügen."}
	menu:addItem{type="separatorline"}

	if glob.mtv_artist then
	for i, v in ipairs(glob.mtv_artist) do
		d = d + 1
		local dkey = godirectkey(d)
		menu:addItem{type="forwarder", name=i .. ": " .. v.name, action="searchliste",enabled=true,id=i,directkey=dkey,hint="Suchwort-Liste für " .. conf.search}
	end
	end
	menu:exec()
	menu:hide()
end

function play_live()
	local video_url = getvideourl(glob.mtv_live_url,"live",true)
	if video_url then
		hideMenu(glob.main_menu)
		vodeoPlay:setSinglePlay()
		vodeoPlay:PlayFile("MTV Live Stream", video_url);
	end
	return MENU_RETURN.EXIT_REPAINT
end

function mtv_listen_menu()
	if glob.mtv == nil then
		return
	end
	hideMenu(glob.main_menu)
	glob.mtv_listen_menu  = menu.new{name="MTV Listen", icon="icon_red"}
	local menu = glob.mtv_listen_menu
	menu:addItem{type="back"}
	menu:addItem{type="separatorline"}
	local d = 0 -- directkey
	for i, v in ipairs(glob.mtv) do
		d = d + 1
		local dkey = godirectkey(d)
		menu:addItem{type="forwarder", name=v.name, action="mtv_liste",enabled=true,id=i,directkey=dkey,hint=v.url}
	end
	menu:exec()
	menu:hide()
	return MENU_RETURN.EXIT_REPAINT
end

function main_menu()
	glob.main_menu  = menu.new{name="MTV", icon="icon_red"}
	local menu = glob.main_menu
	local d = 1 -- directkey

	menu:addKey{directkey=RC["info"], id=mtv_version, action="info"}
	menu:addItem{type="back"}
	menu:addItem{type="separatorline"}
	menu:addItem{type="forwarder", name="MTV Listen", action="mtv_listen_menu", enabled=true,
	id="dummy"..d, directkey=godirectkey(d),hint="MTV Listen"}
        d=d+1
	menu:addItem{type="separatorline"}
	menu:addItem{type="forwarder", name="Suche nach Künstler", action="search_artists", enabled=true,
	id="find", directkey=godirectkey(d),hint="Suche nach Künstler"}
	d=d+1
	menu:addItem{type="keyboardinput", action="setvar", id="search", name="Künstler Name:", value=conf.search,directkey=godirectkey(d),hint_icon="hint_service",hint="Nach welchem Künstler soll gesucht werden ?"}
	menu:addItem{type="separatorline"}
	d=d+1
	menu:addItem{type="forwarder", name="MTV Live", action="play_live", enabled=(glob.mtv_live_url~=nil),
	id="dummy", directkey=godirectkey(d),hint="MTV Live Stream"}

	menu:addItem{type="separatorline"}
	d=d+1
	menu:addItem{type="forwarder", name="Einstellungen", action="setings", enabled=true,
	id="dummy"..d, directkey=godirectkey(d),hint="Einstellungen"}
	menu:exec()
end

function main()
	init()
	loadConfig()
	glob.have_rtmpdump=nil
	if conf.hlsflag then
		glob.have_rtmpdump=which("ffmpeg")
	else
		glob.have_rtmpdump=which("rtmpdump")
	end
	main_menu()
	saveConfig()
	collectgarbage()
end

main()
