dofile(ProcessSkinFilePath("$/init.lua"))

BG = AllocVertices(4)
bg1 = {u=0.0, v=0.0, r=255, g=255, b=255, a=255, x=  0, y=  0, z=0} -- top left
bg2 = {u=0.0, v=272, r=255, g=255, b=255, a=255, x=  0, y=272, z=0} -- bottom left
bg3 = {u=480, v=0.0, r=255, g=255, b=255, a=255, x=480, y=  0, z=0} -- top right
bg4 = {u=480, v=272, r=255, g=255, b=255, a=255, x=480, y=272, z=0} -- bottom right
SetVertices(BG, 0, bg1, bg2, bg3, bg4)

-- We'll assume this doesn't change during execution
DiskFree = GetDiskFreePercent() * 100

function FrameBegin()
	Buttons = GetButtons()
	
	-- Handle menu controls
	if not IgnoreCursor then
		local Moved = true
		if Buttons.up then
			Cursor = Cursor - 1
			SoundEffect_Replay(Sound)
		elseif Buttons.down then
			Cursor = Cursor + 1
			SoundEffect_Replay(Sound)
		elseif Buttons.left then
			Cursor = Cursor - 10
			SoundEffect_Replay(Sound)
		elseif Buttons.right then
			Cursor = Cursor + 10
			SoundEffect_Replay(Sound)
		elseif Buttons.l then
			Cursor = 0
			MenuID = MenuID - 1
			SoundEffect_Replay(Sound)
		elseif Buttons.r then
			Cursor = 0
			MenuID = MenuID + 1
			SoundEffect_Replay(Sound)
		elseif Buttons.accept then MenuAcceptFunc[MenuID]()
		elseif Buttons.cancel then MenuCancelFunc[MenuID]()
		elseif Buttons.triangle then MenuTriangleFunc[MenuID]()
		elseif Buttons.square then MenuSquareFunc[MenuID]()
		else Moved = false end
		
		if Moved then
			IgnoreCursor = true -- Don't move again until button is released
			-- todo: play sound
			
			-- Ensure we're in a menu that exists
			if MenuID > NumMenus then MenuID = 1
			elseif MenuID < 1 then MenuID = NumMenus
			end
			
			-- If we just switched to the file selector for the first time,
			-- read the file list.
			if MenuID == FileMenuID and not Files then ReadCurDir() end
			
			-- Ensure the cursor is visible and within the menu
			if Cursor < 0 then Cursor = MenuNumOpts[MenuID] - 1
			elseif Cursor > MenuNumOpts[MenuID] - 1 then Cursor = 0
			end
				
			if Cursor < Skip then Skip = Cursor
			elseif Cursor >= (Skip + NumLines)
			then Skip = (Cursor - NumLines) + 1
			end
		end
	else
		-- If all above buttons are released then the cursor can respond again
		-- "if ... then else" is shorter than writing "and not" several times
		-- when checking that several variables are false
		if Buttons.up or Buttons.down or Buttons.left or Buttons.right
		or Buttons.l or Buttons.r or Buttons.accept or Buttons.cancel
		or Buttons.triangle or Buttons.square then else
			IgnoreCursor = false
		end
	end
	
	-- Fun: use analog stick to adjust BG saturation/value
	BGSaturation = BGSaturation - ((Buttons.analogx - 127) / 10230)
	if BGSaturation < 0 then BGSaturation = 0
	elseif BGSaturation > 1 then BGSaturation = 1
	end

	BGValue = BGValue - ((Buttons.analogy - 127) / 10230)
	if BGValue < 0 then BGValue = 0 elseif BGValue > 1 then BGValue = 1 end

	-- Fade in background
	if BGValueCount > 0 then
		BGValue = BGValue + (1 / 127)
		BGValueCount = BGValueCount - 1
	end
	
	-- Make the background have flowing colours, which looks cooooool.
	-- Comment this block to have a nice sky blue instead.
	--[
	local rt = Rot * 1.5
	bg1.r, bg1.g, bg1.b = HSVToRGB((rt + 180) % 360, BGSaturation, BGValue)
	bg2.r, bg2.g, bg2.b = HSVToRGB((rt + 270) % 360, BGSaturation, BGValue)
	bg3.r, bg3.g, bg3.b = HSVToRGB((rt + 90) % 360, BGSaturation, BGValue)
	bg4.r, bg4.g, bg4.b = HSVToRGB(rt % 360, BGSaturation, BGValue)
	SetVertices(BG, 0, bg1, bg2, bg3, bg4) --]]
	
	-- Set up frame
	sceGuClearDepth(0)
	sceGuClear(GU_DEPTH_BUFFER_BIT)
	ResetMatrices()
	
	-- Draw background
	sceGuDisable(GU_DEPTH_TEST)
	UseTexture(BGTexture, true)
	RenderVertices(BG, 0, 4, GU_TRIANGLE_STRIP, GU_TRANSFORM_2D)
	
	-- Draw cube
	sceGuEnable(GU_DEPTH_TEST)
	sceGuDisable(GU_TEXTURE_2D)
	
	Translate(0, 0, -1.75)
	RotateDegrees(Rot, Rot / 25, Rot * 2)
	RenderVertices(Cube, 0, 4, GU_TRIANGLE_STRIP, GU_TRANSFORM_3D)
	RenderVertices(Cube, 4, 4, GU_TRIANGLE_STRIP, GU_TRANSFORM_3D)
	RenderVertices(Cube, 8, 4, GU_TRIANGLE_STRIP, GU_TRANSFORM_3D)
	RenderVertices(Cube, 12, 4, GU_TRIANGLE_STRIP, GU_TRANSFORM_3D)
	RenderVertices(Cube, 16, 4, GU_TRIANGLE_STRIP, GU_TRANSFORM_3D)
	RenderVertices(Cube, 20, 4, GU_TRIANGLE_STRIP, GU_TRANSFORM_3D)
	
	Rot = Rot + 0.25
end

function FrameEnd()
	local r,g,b = HSVToRGB((Rot * 2) % 360, 1, 1)
	local Time = GetLocalTime() -- heh
	local Battery = GetBattery()
	local Speed = GetCPUSpeed()
	FrameBuf = GetFrameBuf()
	
	-- This debug text looks kinda neat so I'm leaving it here.
	BitmapFont_DrawString(FrameBuf, Font, 428, 11, FONT_DRAW_XOR, 255, 255, 255,
		0, tostring(Rot), round(tostring(r), 3), round(tostring(g), 3),
		round(tostring(b), 3), tostring(Cursor) .. "," .. tostring(Skip),
		tostring(ScrollX), tostring(BGSaturation),
		tostring(BGValue), tostring(Buttons.analogx), tostring(Buttons.analogy),
		tostring(NumberScrollTimer))
		
	-- This would be a good place to put your name and phone number so anyone
	-- that finds your PSP can return it to you
	BitmapFont_DrawString(FrameBuf, Font, 350, 224, FONT_DRAW_NORMAL, 255, 255, 255, 0,
		"Your Name Here", "1-234-567-8901")
		
	-- Fancy text scroller
	BitmapFont_EnableLineWrap(Font, false)
	BitmapFont_DrawString(FrameBuf, Font, ScrollX, 0, FONT_DRAW_XOR, 128, 128, 128, 0,
		 "Playstation Portable - Firmware v5.00m33-6 - Params=43 68 65 65 73 65 20 74 6F 61 73 74")
	BitmapFont_EnableLineWrap(Font, true)
	
	ScrollX = ScrollX - 1
	-- The value to check for should be about the width of the string in pixels,
	-- negative. By using a slightly lower number (i.e. further from zero),
	-- and/or increasing the value it resets to, you delay the reappearance.
	if ScrollX < -650 then ScrollX = 490 end
	
	-- Draw menu
	DrawMenu(MenuX[MenuID], MenuY[MenuID], MenuTable[MenuID], r, g, b,
		MenuDispKey[MenuID])
	BitmapFont_DrawString(FrameBuf, Font, 102, 238, FONT_DRAW_XOR, r, g, b, 0,
		".root//PSP::" .. MenuTitle[MenuID])
			
	-- Draw some random scrolling numbers to fill in the empty space
	if not UseBGImage then
		NumberScrollTimer = NumberScrollTimer - 1
		if NumberScrollTimer < 1 then
			-- Scroll up
			NumberScrollTimer = math.random(5, 100)
			if NumberScrollSetSize > 0 and NumberScrollYPos > 10 then
				NumberScrollYPos = NumberScrollYPos - 10
			end
			
			-- Add a new random number
			-- If we just do math.random(1, 1000000) it tends to return mostly
			-- 5 and 6-digit numbers, so randomize the number of digits too.
			table.insert(NumberScrollSet, math.random(100, 10 ^ math.random(3, 7)))
			
			-- Remove numbers from the top of the table
			if NumberScrollSetSize < NumberScrollSetSizeMax then
				NumberScrollSetSize = NumberScrollSetSize + 1
			else
				table.remove(NumberScrollSet, 1)
			end
		end
		
		-- Draw the numbers, right-aligned
		-- This handles variable-width fonts as long as all digits are the same
		-- width, so the numbers will be right-aligned.
		for i = 1, NumberScrollSetSize do
			BitmapFont_DrawString(FrameBuf, Font,
				32 + ((7 - NumDigits(NumberScrollSet[i])) * 8),
				(i * 10) + NumberScrollYPos,
				FONT_DRAW_XOR, 255, 255, 255, 0, tostring(NumberScrollSet[i]))
		end
	end
	
	-- Draw status
	BitmapFont_DrawString(FrameBuf, Font, 282, 250, FONT_DRAW_NORMAL, r, g, b, 255,
		string.format("%u%% DISK FREE", DiskFree))
	
	BitmapFont_DrawString(FrameBuf, Font, 0, 262, FONT_DRAW_NORMAL, r, g, b, 255,
		string.format("%d/%d/%02d %02d:%02d:%02d CPU %1.1f/%1.1f Batt %d%% %dC %1.3fV %dmin",
			Time.year, Time.month, Time.day, Time.hour, Time.minute,
			Time.second, Speed.cpu, Speed.bus, Battery.percent,
			Battery.temperature, Battery.voltage, Battery.time))
end