local map_settings = theater.settings.maps[game.GetMap()]
if !map_settings then return end

local theater_volume = CreateClientConVar("theater_volume", 50, FCVAR_ARCHIVE)
local theater_fps = CreateClientConVar("theater_fps", 30, FCVAR_ARCHIVE)
local theater_res = CreateClientConVar("theater_resolution", 1, FCVAR_ARCHIVE)

local display
cvars.AddChangeCallback("theater_volume", function(cvar, _, value)
	timer.Create("theater_volume", 0, 1, function()
		if IsValid(display) then
			display:RunJavascript("if (player != null) { player.setVolume("..(tonumber(value) or 0)..") }")
		end
	end)
end)

cvars.AddChangeCallback("theater_resolution", function(cvar, _, value)
	timer.Create("theater_resolution", 0, 1, function()
		if IsValid(display) then
			local index = tonumber(value) or 1

			if !index or index < 0.1 or index > 2 then
				index = 1
				RunConsoleCommand("theater_resolution", 1)
			end

			if IsValid(display) then
				display:SetSize(1920 * math.Clamp(theater_res:GetFloat(), 0.1, 2), 1080 * math.Clamp(theater_res:GetFloat(), 0.1, 2))
			end
		end
	end)
end)

surface.CreateFont("theater_Big", {font = "Arial", size = 256, weight = 800})
surface.CreateFont("theater_Small", {font = "Arial", size = 128, weight = 800})

local local_ply
local mat
local function DrawBillboard()
	local_ply = local_ply or LocalPlayer()
	if local_ply.theater_Inside == true then
		cam.Start3D2D(map_settings.origin, map_settings.angles, 0.1)
			surface.SetDrawColor(25, 25, 25, 255)

			local w, h = map_settings.width * 2.5, map_settings.height * 2.5

			surface.DrawRect(0, 0, w, h)

			if ((theater.video or "_idle") != "_idle") then
				if IsValid(display) then
					draw.SimpleText("Lädt Film...", "theater_Big", w / 2, (h / 2) + math.sin(SysTime() * 2.5) * 25 - 80, color_white, 1, 1)

					if !display.NextHTMLTextureThink or SysTime() > (display.NextHTMLTextureThink or 0) then
						display:UpdateHTMLTexture()
						display.NextHTMLTextureThink = SysTime() + (1 / math.max(theater_fps:GetInt(), 1))

						mat = display:GetHTMLMaterial()
					end

					local pw, ph = display:GetSize()

					w = w / pw
					h = h / ph

					pw = pw * (math.pow(2, math.ceil(math.log(pw) / math.log(2))) / pw)
					ph = ph * (math.pow(2, math.ceil(math.log(ph) / math.log(2))) / ph)

					if mat then
						surface.SetDrawColor(255, 255, 255)
						surface.SetMaterial(mat)
						surface.DrawTexturedRect(0, 0, w * pw, h * ph)
					end
				end
			else
				if IsValid(display) then
					display:Remove()
				end

				draw.SimpleText("Kein Film in der Warteschleife...", "theater_Big", w / 2, (h / 2) + math.sin(SysTime() * 2.5) * 25 - 80, color_white, 1, 1)
				draw.SimpleText("Schreibe \"/kino\", um einen Film anzufragen.", "theater_Small", w / 2, (h / 2) + 200, color_white, 1, 1)
			end
		cam.End3D2D()
	end
end
hook.Add("PostDrawOpaqueRenderables", "theater_DrawBillboard", DrawBillboard)

local function CreateDisplay(time)
	local ply = LocalPlayer()
	if !IsValid(ply) then return end

	if (ply.theater_Inside and (theater.video or "_idle") != "_idle") then
		if IsValid(display) then
			display:Remove()
		end

		local html = [[
			<html><body style="overflow: hidden;">
			<div id="player"></div>
			<script>
				var tag = document.createElement('script');
				tag.src = "https://www.youtube.com/iframe_api";
				var firstScriptTag = document.getElementsByTagName('script')[0];
				firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
				var player;

				function onYouTubeIframeAPIReady() {
					player = new YT.Player('player', {
					height: '100%',
					width: '100%',
					videoId: ']]..(theater.video or "S5PvBzDlZGs")..[[',
					wmode: "transparent",
					host: "https://www.youtube-nocookie.com",
					events: {
						'onReady': onPlayerReady
					}
				});
			}

			function onPlayerReady(event) {
				event.target.setVolume(]]..theater_volume:GetInt()..[[);
				event.target.seekTo(]]..tostring(time)..[[);
				event.target.playVideo();
			}

			</script>
			</body>
			</html>
		]]

		display = vgui.Create("HTML", vgui.GetWorldPanel())
		display:SetHTML(html)
		display:SetSize(1920 * math.Clamp(theater_res:GetFloat(), 0.1, 2), 1080 * math.Clamp(theater_res:GetFloat(), 0.1, 2))

		display:SetPaintedManually(true)

		display:SetKeyboardInputEnabled(false)
		display:SetMouseInputEnabled(false)

		display.ConsoleMessage = function()
		end

		display.OnDocumentReady = function()
		end

		display:Stop()
	elseif IsValid(display) then
		display:Remove()
	end
end

net.Receive("theater_SendStatus", function(length)
	local ply = LocalPlayer()
	if !IsValid(ply) then return end

	ply.theater_Inside = net.ReadBit() == 1

	local time = net.ReadFloat()

	CreateDisplay(time)
end)

local SKIN = {}

SKIN.DermaVersion = 1
SKIN.GwenTexture = Material("gwenskin/GModDefault.png")

function SKIN:PaintFrame(panel, w, h)
	surface.SetDrawColor(255, 255, 255)
	surface.DrawRect(0, 0, w, h)
	surface.SetDrawColor(127, 127, 127)
	surface.DrawOutlinedRect(0, 0, w, h)
	surface.SetDrawColor(50, 50, 50)
	surface.DrawRect(0, 0, w, 25)
end

function SKIN:PaintButton(panel, w, h)
	if panel:GetText() == "" then return end
	if panel.Depressed or panel:IsSelected() or panel:GetToggle() then
	elseif panel:GetDisabled() then
		surface.SetDrawColor(170, 170, 170)
	elseif panel.Hovered then
		surface.SetDrawColor(100, 100, 100)
	else
		surface.SetDrawColor(50, 50, 50)
	end
	surface.DrawRect(0, 0, w, h)
	surface.SetDrawColor(0, 0, 0)
	surface.DrawOutlinedRect(0, 0, w, h)
end
derma.DefineSkin("TheaterSkin", "l337", SKIN)

local PANEL = {}

function PANEL:InitCustomControls(ctrl)
	local qbtn = ctrl:Add("DButton")
	qbtn:Dock(RIGHT)
	qbtn:SetWide(100)
	qbtn:SetText("Titel hinzufügen")
	qbtn.DoClick = function()
		self:OnURLSelected(ctrl.AddressBar:GetText())
	end
	self.addToQueueButton = qbtn
end

function PANEL:Init()
	self.browser = self:Add("DHTML")
	self.browser:Dock(FILL)
	self.browser:OpenURL("https://youtube.com/")
	self.browser.Paint = function() end
	local oldcm = self.browser.ConsoleMessage
	self.browser.ConsoleMessage = function(pself, msg, ...)
		if msg then
			if string.find(msg, "XMLHttpRequest") then return end
			if string.find(msg, "Unsafe JavaScript attempt to access") then return end
		end
		return oldcm(pself, msg, ...)
	end
	self.browser.UrlChanged = function() end
	self.browser:AddFunction("theater", "CurrentURL", function(curl)
		if curl != self.browser._lastcurl then
			self.browser:UrlChanged(curl)
			self.browser._lastcurl = curl
		end
	end)
	self.browser:AddFunction("theater", "QueueURL", function(url)
		self:OnURLSelected(url)
	end)
	function self.browser:RequestCurrentURL()
		self:RunJavascript("theater.CurrentURL(window.location.href);")
	end
	self.controls = self:Add("DHTMLControls")
	self.controls:Dock(TOP)
	self.controls:SetHTML(self.browser)
	self:InitCustomControls(self.controls)
	local function UrlChanged(u)
		local addressBar = self.controls.AddressBar
		if vgui.GetKeyboardFocus() != addressBar then
			addressBar:SetText(u)
		end
		local enabled = string.match(u, "youtu.?be[.com]?") and u != "https://www.youtube.com/"
		self:OnURLValidityChanged(enabled)
	end
	self.browser.OnDocumentReady = function(s, u)
		UrlChanged(u:find("^data:text") and "home" or u)
	end
	self.browser.UrlChanged = function(s, u)
		UrlChanged(u)
	end
	self.browser.OnChangeTitle = function(s, u)
		self.browser:RequestCurrentURL()
	end
end

function PANEL:OnURLValidityChanged(b)
	self.addToQueueButton:SetEnabled(b)
end

function PANEL:OnURLSelected(url)
end
vgui.Register("theater_VideoSelector", PANEL, "Panel")

local RequestFrame
local function VideoSelector(onAccept)
	local frame = vgui.Create("DFrame")
	frame:SetTitle("Titelauswahl")
	frame:SetSkin("TheaterSkin")
	frame:SetSize(ScrW() * 0.8, ScrH() * 0.8)
	frame:Center()

	RequestFrame = frame

	local vidsel = frame:Add("theater_VideoSelector")
	vidsel.OnURLSelected = function(_, url)
		frame:Close()
		onAccept(url)
	end
	vidsel:Dock(FILL)

	frame:MakePopup()
end

local theaterFrame
net.Receive("theater_OpenMenu", function(length)
	if IsValid(theaterFrame) then return end

	theaterFrame = vgui.Create("DFrame")
	theaterFrame:MakePopup()
	theaterFrame:SetTitle("Kino-Interface")
	theaterFrame:SetSize(250, 280)
	theaterFrame:Center()
	theaterFrame:ParentToHUD()

	theaterFrame:ShowCloseButton(false)

	local close = vgui.Create("DButton", theaterFrame)
	close:SetSize(40, 24)
	close:SetPos(theaterFrame:GetWide() - close:GetWide(), 0)
	close:SetTextColor(color_white)
	close:SetFont("Marlett")
	close:SetText("r")

	close.DoClick = function()
		theaterFrame:Close()

		surface.PlaySound("ui/buttonclick.wav")
	end

	close.Paint = function(slf, w, h)
		if slf:IsHovered() then
			draw.RoundedBox(0, 0, 0, w, h - 1, Color(200, 50, 50))
		end
	end

	theaterFrame.Paint = function(self, w, h)
		draw.RoundedBox(2, 0, 0, w, h, Color(35, 35, 35, 255))
	end

	local opened = false
	theaterFrame.Think = function(self)
		if input.IsKeyDown(KEY_F2) then
			if opened then
				self:Remove()
			end
		else
			opened = true
		end
	end

	local volume = theaterFrame:Add("DNumSlider")
	volume:SetMin(0)
	volume:SetMax(100)
	volume:SetDecimals(0)
	volume:SetConVar("theater_volume")
	volume:SetText("Volumen")
	volume:Dock(TOP)

	local fps = theaterFrame:Add("DNumSlider")
	fps:SetMin(30)
	fps:SetMax(60)
	fps:SetDecimals(0)
	fps:SetConVar("theater_fps")
	fps:SetText("Film-FPS")
	fps:Dock(TOP)
	fps:DockMargin(0, 5, 0, 0)

	local res = theaterFrame:Add("DNumSlider")
	res:SetMin(0.1)
	res:SetMax(1)
	res:SetDecimals(2)
	res:SetConVar("theater_resolution")
	res:SetText("Film-Auflösung")
	res:Dock(TOP)
	res:DockMargin(0, 5, 0, 0)

	local skip = theaterFrame:Add("DButton")
	skip:SetText("Überspringen abstimmen")
	skip.DoClick = function()
		if !theater.settings.AllowSkipVote then	return end
		surface.PlaySound("ui/buttonclick.wav")
		RunConsoleCommand("theater_voteskip")
	end
	skip:SetEnabled(theater.settings.AllowSkipVote)
	skip:Dock(TOP)
	skip:DockMargin(0, 5, 0, 0)

	local url = theaterFrame:Add("DButton")
	url:SetText("Film abspielen")
	url.DoClick = function()
		if LocalPlayer():Team() != TEAM_THEATER then return end
		surface.PlaySound("ui/buttonclick.wav")
		Derma_StringRequest("Film abspielen", "Bitte gebe einen gültigen YouTube-Link an:", "", function(text) RunConsoleCommand("theater_requestvideo", text) end, nil, "OK", "Abbrechen")
	end
	url:SetEnabled(LocalPlayer():Team() == TEAM_THEATER)
	url:Dock(TOP)
	url:DockMargin(0, 10, 0, 0)

	local refresh = theaterFrame:Add("DButton")
	refresh:SetText("Film von vorne abspielen")
	refresh.DoClick = function()
		if LocalPlayer():Team() != TEAM_THEATER then return end
		surface.PlaySound("ui/buttonclick.wav")
		RunConsoleCommand("theater_refreshmovie")
	end
	refresh:SetEnabled(LocalPlayer():Team() == TEAM_THEATER)
	refresh:Dock(TOP)
	refresh:DockMargin(0, 5, 0, 0)

	local skip = theaterFrame:Add("DButton")
	skip:SetText("Überspringen erzwingen")
	skip.DoClick = function()
		if LocalPlayer():Team() != TEAM_THEATER then return end
		surface.PlaySound("ui/buttonclick.wav")
		RunConsoleCommand("theater_skipmovie")
	end
	skip:SetEnabled(LocalPlayer():Team() == TEAM_THEATER)
	skip:Dock(TOP)
	skip:DockMargin(0, 5, 0, 0)

	local yt = theaterFrame:Add("DButton")
	yt:SetText("Filmauswahl öffnen")
	yt.DoClick = function()
		if LocalPlayer():Team() != TEAM_THEATER then return end
		surface.PlaySound("ui/buttonclick.wav")
		VideoSelector(function(url)
			RunConsoleCommand("theater_requestvideo", url)
		end)
	end
	yt:SetEnabled(LocalPlayer():Team() == TEAM_THEATER)
	yt:Dock(TOP)
	yt:DockMargin(0, 5, 0, 0)
end)

net.Receive("theater_SendVideo", function(length)
	theater.video = net.ReadString()
end)