-- parse best m3u8 RESOLUTION
-- add parse Referer in Url by GetAway
-- Version 1.2

if #arg < 1 then return nil end

json = require "json"

local _url = arg[1]
local Curl = nil
local ret = {}
local CONF_PATH = "/var/tuxbox/config/"
if DIR and DIR.CONFIGDIR then
	CONF_PATH = DIR.CONFIGDIR .. '/'
end

function extractParam(hdrs, paramName)
	local paramPos = string.find(hdrs, paramName)
	if paramPos then
		local referer = hdrs:match("Referer=([^&]+)")
		return referer
	end
	return ""
end

function generateHeaders(Url)
	local headers = {}
		local pos = string.find(string.reverse(Url), '#')
		if pos then
		    local hdrs = string.sub(Url, -pos + 1)
		    val = extractParam(hdrs, "Referer=")
		    if val ~= "" then
		        table.insert(headers, "Referer: " .. val)
		    end
			if #headers > 0 then
				io.write("Headers: ")
				for i, header in ipairs(headers) do
					print(header)
				end
				Url = string.sub(Url, 1, -pos - 1)
			end
		end
	return headers, Url
end

function getdata(Url,Agent)
	if Url == nil then return nil end
	if Curl == nil then
		Curl = curl.new()
	end
	if Agent == nil then Agent = "Mozilla/5.0" end
	local headers, Url = generateHeaders(Url)

	local ret, data = Curl:download{ url=Url, A=Agent, httpheader=headers, connectTimeout=5, maxRedirs=5, followRedir=true}
	if ret == CURL.OK then
		return data
	else
		return nil
	end
end

function getMaxRes()
	local maxRes = 1280
	local Nconfig = configfile.new()
	if Nconfig then
		Nconfig:loadConfig(CONF_PATH .. "neutrino.conf")
		maxRes = Nconfig:getInt32("livestreamResolution", 1280)
	end
	return maxRes
end

function getVideoUrl(m3u8_url)
	if m3u8_url == nil then return nil end
	local tmpurl = m3u8_url:lower()
	if not tmpurl:find('m3u8') then return -2 end

	local res = 0
	local agent = m3u8_url:match("User%-Agent=([^&]+)")
	local data = getdata(m3u8_url,agent)
	if data then
		res = 1
		entry = {}
		entry['url']  = m3u8_url
		entry['name'] = "org m3u8 url"
		ret[1] = {}
		ret[1] = entry

		local host = m3u8_url:match('([%a]+[:]?//[_%w%-%.]+)/')
		local lastpos = (m3u8_url:reverse()):find("/")
		local hosttmp = m3u8_url:sub(1,#m3u8_url-lastpos)
		if hosttmp then
			host = hosttmp .."/"
		end

		local revision = 0
		local maxRes = getMaxRes()
		if APIVERSION ~= nil and (APIVERSION.MAJOR > 1 or ( APIVERSION.MAJOR == 1 and APIVERSION.MINOR > 82 )) then
			M = misc.new()
			revision = M:GetRevision()
		end
		local audio_url = nil
		if revision == 1 then -- separate audio for hd51 and co
			local Nconfig	= configfile.new()
			local lang1,lang2,lang3 = nil,nil,nil
			Nconfig:loadConfig(CONF_PATH .. "neutrino.conf")
			lang1 = Nconfig:getString("pref_lang_0", "#")
			lang2 = Nconfig:getString("pref_lang_1", "#")
			lang3 = Nconfig:getString("pref_lang_2", "#")
			if lang1 == "#" then lang1 = nil else lang1 = lang1:lower() lang1 = lang1:sub(1,3) end
			if lang2 == "#" then lang2 = nil else lang2 = lang2:lower() lang2 = lang2:sub(1,3) end
			if lang3 == "#" then lang3 = nil else lang3 = lang3:lower() lang3 = lang3:sub(1,3) end
			if lang1 == nil then
				lang1 = Nconfig:getString("language", "english")
				if lang1 == nil then
					lang1 = "eng"
				else
					lang1 = lang1:lower() lang1 = lang1:sub(1,3)
				end
			end

			local l1,l2,l3,l4,l = nil,nil,nil,nil,nil
			--for adata in data:gmatch('TYPE%=AUDIO.GROUP%-ID=".-",(.-)\n') do
			for adata in data:gmatch('TYPE%=AUDIO,(.-)\n') do
				local lname = adata:match('NAME="(.-)"')
				local lang = adata:match('LANGUAGE="(.-)"')
				if lang == nil and lname ~= nil then lang = lname end
				local aurl = adata:match('URI="(.-)"')
				if aurl then
					local low_lang = lang:lower()
					if l1 == nil and lname and lang1 and low_lang == lang1 then
						l1 = aurl
					elseif l2 == nil and lname and lang2 and low_lang == lang2 then
						l2 = aurl
					elseif l3 == nil and lname and lang3 and low_lang == lang3 then
						l3 = aurl
					elseif l4 == nil and lname and low_lang == "deu" then
						l4 = aurl
					elseif l == nil then
						l = aurl
					end
				end
			end
			audio_url = l1 or l2 or l3 or l4 or l
		end
		local allres = {}
		local j = 1
		local minRes = 0

		local mask = 'BANDWIDTH=(%d+).-RESOLUTION=(%d+)x(%d+).-\n(.-)\n'
		if data:find("#EXT%-X%-STREAM%-INF:") then
			data = data:gsub("#EXT%-X%-I%-FRAME%-STREAM%-INF:[^\n]*\n?", "")
		end

		for band, res1, res2, url in data:gmatch(mask) do
			local nr = tonumber(res1)
			if nr <= maxRes then
				minRes = nr
			end
			allres[j] = nr
			j=j+1
		end
		if minRes == 0 and j>1 then maxRes = math.min(unpack(allres)) end
		allres = {}
		local c = 0
		for band, res1, res2, url in data:gmatch(mask) do
			if url and res1 and url:sub(1,3) ~= '../' then
				local nr = tonumber(res1)
					res=nr
					if host and url:sub(1,4) ~= "http" then
						if host:sub(-1) == '/' and url:sub(1,1) == '/' then
							local _, slash_count = host:gsub("/", "")
							if slash_count ~= 3 or host:sub(-1) ~= "/" then
								host = host:match("^([hH][tT][tT][pP][sS]?://[^/]+/)")
							end
							url = host:sub(1,-2) .. url
						else
							url = host .. url
						end
					end
					if audio_url and host and audio_url:sub(1,4) ~= "http" then
						audio_url = host .. audio_url
					end
					entry = {}
					url = url:gsub("\x0d","")
					entry['url']  = url
					if audio_url then
						audio_url = audio_url:gsub("\x0d","")
						entry['url2'] = audio_url
					end
					if agent then entry['header']  = agent end
					entry['band'] = band
					entry['res1'] = res1
					entry['res2'] = res2
					entry['name'] = "RESOLUTION=" .. res1 .. "x" .. res2
					c = c + 1
					ret[c] = {}
					ret[c] = entry
					if res == 1 then res = 2 end
				if res1 then
					local Res = res1 .. "x" .. res2
					if allres[Res] ~= true then
						allres[Res] = true
					end
				end
			end
		end
		if allres then
			local otherRes = ''
			for Res, _ in pairs(allres) do
				if not entry['name']:find(Res) then
					otherRes = otherRes .. ' ' .. Res
				end
			end
			if #otherRes > 1 then entry['name'] = entry['name'] .. ' :' .. otherRes end
		end

		if res == 1 then
			local allbands = {}
			for band, url in data:gmatch('BANDWIDTH=(%d+).-\n(.-)\n') do
				if url and band  and url:sub(1,3) ~= '../' then
					local nr = tonumber(band)
					if nr > res then
						res=nr
						if host and url:sub(1,4) ~= "http" then
							if host:sub(-1) == '/' and url:sub(1,1) == '/' then
								local _, slash_count = host:gsub("/", "")
								if slash_count ~= 3 or host:sub(-1) ~= "/" then
									host = host:match("^([hH][tT][tT][pP][sS]?://[^/]+/)")
								end
								url = host:sub(1,-2) .. url
							else
								url = host .. url
							end
						end
						if audio_url and host and audio_url:sub(1,4) ~= "http" then
							audio_url = host .. audio_url
						end
						entry = {}
						url = url:gsub("\x0d","")
						entry['url']  = url
						if audio_url then
							audio_url = audio_url:gsub("\x0d","")
							entry['url2'] = audio_url
						end
						if agent then entry['header']  = agent end
						entry['band'] = band
						local otherBand = ''
						entry['name'] = "BANDWIDTH=" .. band
						c = c + 1
						ret[c] = {}
						ret[c] = entry
					end
					if band then
						if allbands[band] ~= true then
							allbands[band] = true
						end
					end
				end
			end
			if allbands then
				local otherBands = ''
				for Band, _ in pairs(allbands) do
					if not entry['name']:find(Band) then
						otherBands = otherBands .. ' ' .. Band
					end
				end
				if #otherBands > 1 then entry['name'] = entry['name'] .. ' :' .. otherBands end
			end
		end
	else
		return -1 --url is offline
	end
	return res
end

local have_url = getVideoUrl(_url)
if have_url > 0 then
	return json:encode(ret)
end
if have_url == -1 then return "" end --url is offline

	entry = {}
	entry['url']  = _url
	entry['band'] = "1"
	entry['res1'] = "1"
	entry['res2'] = "1"
	entry['name'] = "not m3u8"
	ret[1] = {}
	ret[1] = entry
	return json:encode(ret)
