frt = Timer.new()
frt:start()
fnt = Font.createProportional()
fnt:setPixelSizes(0, 14)
cl1=Color.new(0,0,0)
cl2=Color.new(127,127,127,127)
cl3=Color.new(255,255,255)
cl4=Color.new(128,128,128)
cl5=Color.new(64,64,64)
pro=Image.load("res/pro.png")
pla=Image.load("res/pla.png")
pau=Image.load("res/pau.png")
sto=Image.load("res/sto.png")

ld=Image.createEmpty(480,272)
txtl=0
function loadtxt(str)
	txtl=txtl+1
	if txtl==18 then txtl=1 ld:clear() end
	ld:fontPrint(fnt, 0, 14*txtl, str, cl3)
	screen:clear()
	screen:blit(0,0,ld)
	screen.waitVblankStart()
	screen:flip()
end

loadtxt("TruFlow for PSP version 1.1")
loadtxt("by Da MerV")
loadtxt("Now Loading... Hold R to recache")
tex={}

function readart(mf)
	local file = io.open(mf)
	local str = file:read(131072)
	file:close()

	local strt = string.find(str, "JFIF")
	if strt then
		image = Image.loadFromMemory(string.sub(str,strt-6,string.find(str, string.char(255,217))+1))
	else
		strt = string.find(str, "PNG")
		if strt then
			image = Image.loadFromMemory(string.sub(str,strt,string.find(str,"IEND")+7))
		else
			image = nil
		end
	end
end

function drawTex(image,album,artist,mfl)
	screen:fillRect(0,0,128,225,cl1)
	Gu.start3d()
	temp = {{0, 0, 0, 0, 0},{image:width(), image:height(), 128, 128, 0}}
	Gu.enable(Gu.TEXTURE_2D)
	Gu.texImage(image)
	Gum.drawArray(Gu.SPRITES, Gu.TEXTURE_32BITF+Gu.VERTEX_32BITF+Gu.TRANSFORM_2D, temp)
	temp = {{0, image:height(), 0, 129, 0},{image:width(), 0, 128, 257, 0}}
	Gu.texImage(image)
	Gum.drawArray(Gu.SPRITES, Gu.TEXTURE_32BITF+Gu.VERTEX_32BITF+Gu.TRANSFORM_2D, temp)
	temp = {{Color.new(0,0,0,160), 0, 128, 0},{Color.new(0,0,0,160), 128, 128, 0},{cl1, 0, 225, 0},{cl1, 128, 225, 0}}
	Gu.disable(Gu.TEXTURE_2D)
	Gum.drawArray(Gu.TRIANGLE_STRIP, Gu.COLOR_8888+Gu.VERTEX_32BITF+Gu.TRANSFORM_2D, temp)
	Gu.end3d()

	temp = Image.createEmpty(256,256)
	temp:blit(0,0,screen,0,0,128,225)

	temp:drawLine(0,0,127,0,cl2)
	temp:drawLine(0,127,127,127,cl2)
	temp:drawLine(0,0,0,127,cl2)
	temp:drawLine(127,0,127,127,cl2)

	temp2 = Image.createEmpty(480,32)
	temp2:fontPrint(fnt, 240-(fnt:getTextSize(album)["width"]/2), 14, album, cl3)
	temp2:fontPrint(fnt, 240-(fnt:getTextSize(artist)["width"]/2), 28, artist, cl3)
	table.insert(tex, {art = temp, text = temp2, mf = mfl})
end

cfgr = io.open("config.ini")
if cfgr then
	gcfgr = cfgr:read("*a")
	if gcfgr=="" then mdir="music" else mdir=gcfgr end
end

cfg = io.open("cache/library.index")
if Controls.read():r() then
	loadtxt("Recache? X:Confirm O:Cancel")
	while true do
		oldinput = input
		input = Controls.read()
		if input:cross() and not oldinput:cross() then cfg:close() cfg=nil break end
		if input:circle() and not oldinput:circle() then break end
	end
end
if cfg then
	function gcfl()
		gls = cfg:read("*l")
		return string.sub(gls,1,string.len(gls)-1)
	end
	total=gcfl()
	if (not total) or (total==0) then cfg=nil end
end
if cfg then
	loadtxt("Reading from cache...")
	total=math.floor(total)
	for i=1,total do
		sfile=gcfl()
		artist=gcfl()
		album=gcfl()
		image=Image.load("cache/"..i..".png")
		drawTex(image,album,artist,sfile)
	end
	cfg:close()
	System.currentDirectory(mdir)
else
	function pcfg()
		cfg = io.open("cache/library.index","w+")
	end
	function iml()
		image = Image.loadFromMemory(ifile:read("*a"))
	end
	function cfm(i)
		loadtxt("Analyzing "..artdir[i].name)
		totl=total+1
		fstr = string.sub(artdir[i].name,1,string.len(artdir[i].name)-4)
		imgfnd=false
		ifile = io.open(fstr..".png", "rb")
		if ifile then
			pcall(iml)
			if image then imgfind=true end
			ifile:close()
		end
		if not imgfnd then
			ifile = io.open(fstr..".jpg", "rb")
			if ifile then
				pcall(iml)
				if image then imgfind=true end
				ifile:close()
			end
		end
		if not imgfnd then
			pcall(readart,artdir[i].name)
			if image then imgfnd=true end
		end
		if not imgfnd then
			image = gen
		end
		image:save(sdir.."/cache/"..totl..".png")
		Mp3me.load(artdir[i].name)
		album,artist=Mp3me.album(),Mp3me.artist()
		cst=artdir[i].name..nl..artist..nl..album..nl
		drawTex(image,album,artist,artdir[i].name)
		image=nil
		loadtxt("Added to library")
	end
	total=0
	gen=Image.load("res/gen.png")
	nl=string.char(13,10)
	loadtxt("Cache not found, indexing music...")
	if not pcall(pcfg) then System.createDirectory(cache) loadtxt("Cache directory created") pcfg()  end
	cfgstr=""
	sdir = System.currentDirectory(mdir)
	artdir = System.listDirectory()
	loadtxt("Writing cache from "..System.currentDirectory())
	for i = 1, table.getn(artdir) do
		if artdir[i].directory == false then
			if string.lower(string.sub(artdir[i].name, -4)) == ".mp3" then
				cst=nil
				pcall(cfm,i)
				if cst then
					total=total+1
					cfgstr=cfgstr..cst
				else
					loadtxt("Problem reading file, skipping")
				end
			end
		end
	end
	cfg:write(total..nl..cfgstr)
	cfg:close()
	cfgstr=nil
	if total==0 then loadtxt("No music files found. Auto exiting in 5 seconds") System.sleep(5000) System.Quit() end
end

function putTex(tex,d,vel)
	mx = 128*d+240
	if d > 1 then mx = 28*d+340 end
	if d < -1 then mx = 28*d+140 end
	my = (1-vel)*(32-((mx-240)^2/512))+(168-((mx-240)^2/3600))
	hl = math.min(16,math.max(-16,(mx-240)/8))
	_l,_r = .005*my*(128+hl),.005*my*(128-hl)
	_w = (64-math.abs(hl))*.005*my
	h = (hl*.005*my)/4
	ax,bx,cx,dx = mx-_w+h,mx+_w+h,mx-_w-h,mx+_w-h
	ay,by,cy,dy = my-_l,my-_r,my+_r,my+_l
	l,r = math.min(255,math.max(127,-mx+495)),math.min(255,math.max(127,mx+15))
	t = (-17*(mx-240)^2)/3840+255
	t1 = {{0,0,Color.new(l,l,l,t),ax,ay,0},{128,0,Color.new(r,r,r,t),bx,by,0},{0,256,Color.new(l,l,l,t),cx,cy,0},{128,256,Color.new(r,r,r,t),dx,dy,0}}
	Gu.enable(Gu.TEXTURE_2D)
	Gu.texImage(tex)
	Gu.texFilter(Gu.LINEAR, Gu.LINEAR)
	Gu.texFunc(Gu.TFX_MODULATE, Gu.TCC_RGBA)
	Gum.drawArray(Gu.TRIANGLE_STRIP, Gu.COLOR_8888+Gu.TEXTURE_32BITF+Gu.VERTEX_32BITF+Gu.TRANSFORM_2D, t1)
end

function timedis()
	tim=Mp3me.gettime()
	stim=string.sub(tim,4,5)*60+string.sub(tim,7,8)
	perc=stim*300/ttim
	screen:fontPrint(fnt, 90, 267+ofst, string.sub(tim,4,8), cl3)
	min=math.floor((ttim-stim)/60)
	sec=(ttim-stim)-(min*60)
	if min<10 then min="0"..min end
	if sec<10 then sec="0"..sec end
	screen:fontPrint(fnt, 349, 267+ofst, min..":"..sec, cl3)
end

function play()
	fail=true
	Mp3me.stop()
	Mp3me.load(tex[cursong].mf)
	Mp3me.play()
	tst=Mp3me.title()
	perc=0
	bar = Image.createEmpty(480,64)
	bar:fontPrint(fnt, 240-(fnt:getTextSize(tst)["width"]/2), 16, tst, cl3)
	bar:blit(90,28,pro)
	bar:blit(48,20,pla)
	tim=Mp3me.songTime()
	ttim=string.sub(tim,4,5)*60+string.sub(tim,7,8)
	pause=false
	fail=false
end

function txt(str,ln)
	screen:fontPrint(fnt, 0, 14*ln, str, cl3)
end

function pmfl()
	if (cursong<total) then
		cursong=cursong+1
		pcall(play)
		if fail then pmfl() else playing = true end
	else
		ofst=.03125
		playing = false
		Mp3me.stop()
		bar:blit(48,20,sto)
	end
end

pos = {x = 1, vel = 0}
playing=false
input = Controls.read()
while not input:start() do
	screen:clear()
	oldinput = input
	input = Controls.read()

	if math.abs(input:analogX()) > 30 then
		targ=nil
		pos.vel = pos.vel+math.abs(input:analogX())*input:analogX()/800000
	else
		pos.vel = pos.vel/1.25
		if math.abs(pos.vel) < .0001 and not targ then
			pos.vel = 0
			pos.x = pos.x + (math.floor(pos.x+.5)-pos.x)/3
			if math.abs(math.floor(pos.x+.5)-pos.x) < .0001 then
				pos.x = math.floor(pos.x+.5)
			end
		end
	end
	if input:left() and not oldinput:left() then
		if targ then
			targ=targ-1
		else
			targ=math.floor(pos.x+.5)-1
		end
	end
	if input:right() and not oldinput:right() then
		if targ then
			targ=targ+1
		else
			targ=math.floor(pos.x+.5)+1
		end
	end
	if input:cross() and not oldinput:cross() then
		if not ofst then ofst=64 end
		targ=math.floor(pos.x+.5)
		cursong=targ
		pcall(play)
		if fail then pmfl() else playing = true end
	end
	if input:square() and not oldinput:square() and playing then
		ofst=.03125
		playing = false
		Mp3me.stop()
		bar:blit(48,20,sto)
	end
	if input:circle() and not oldinput:circle() and playing then
		Mp3me.pause()
		if pause then
			pause=false
			bar:blit(48,20,pla)
		else
			pause=true
			bar:blit(48,20,pau)
		end
	end
	if input:l() and not oldinput:l() and playing and (cursong>1) then
		cursong=cursong-1
		pcall(play)
		if fail then pmfl() else playing = true end
	end
	if input:r() and not oldinput:r() and playing and (cursong<total) then
		cursong=cursong+1
		pcall(play)
		if fail then pmfl() else playing = true end
	end
	if input:select() and not oldinput:select() then
		screen:clear()
		txt("Help",1)
		txt("Cross: plays the selected album",3)
		txt("Square: stops playing the current song",4)
		txt("Circle: pauses/plays the current song",5)
		txt("L/R: play previous/next song",6)
		txt("Left/Right: browse albums one by one",7)
		txt("Analog nub: scrolls through albums",8)
		txt("Select: help",9)
		txt("Home: exit",10)
		txt("Press X to close",12)
		screen.waitVblankStart()
		screen:flip()
		while true do
			oldinput = input
			input = Controls.read()
			if input:cross() and not oldinput:cross() then break end
		end
		screen:clear()
	end
	if targ then
		pos.vel = 0
		pos.x = pos.x + (targ-pos.x)/5
	end
	pos.x = pos.x + pos.vel 
	if pos.x < .5 then
		pos.x = .5
		pos.vel = -(pos.vel/3)
		targ = nil
	elseif pos.x > total+.499 then
		pos.x = total+.499
		pos.vel = -(pos.vel/3)
		targ = nil
	end

	--screen:print(0,0,"fps: "..1000/frt:reset(),cl3)
	frt:start()


	Gu.start3d()
		tile = math.floor(pos.x+.5)
		ofs = tile-pos.x
		for e=-5,0 do
			if tile+e>0 then
				putTex(tex[tile+e].art,e+ofs,math.abs(pos.vel))
			end
		end
		for e=5,0,-1 do
			if tile+e<total+1 then
				putTex(tex[tile+e].art,e+ofs,math.abs(pos.vel))
			end
		end
	Gu.end3d()
	fn1,cofs=128*ofs,Color.new(255,255,255,-1020*ofs^2+255)
	Gu.start3d()
		Gu.enable(Gu.TEXTURE_2D)
		Gu.texImage(tex[tile].text)
		Gu.texFunc(Gu.TFX_MODULATE, Gu.TCC_RGBA)
		Gum.drawArray(Gu.TRIANGLE_STRIP, Gu.COLOR_8888+Gu.TEXTURE_32BITF+Gu.VERTEX_32BITF+Gu.TRANSFORM_2D, {{0,0,cofs,fn1,30,0},{480,0,cofs,480+fn1,30,0},{0,32,cofs,fn1,62,0},{480,32,cofs,480+fn1,62,0}})
	Gu.end3d()
	if playing then
		if ofst>0 then ofst=math.floor(ofst/2) end
		pcall(timedis)
		if Mp3me.eos()=="true" then
			if cursong==total then
				ofst=.03125
				playing = false
				Mp3me.stop()
				bar:blit(48,20,sto)
			else
				cursong=cursong+1
				pcall(play)
				if fail then pmfl() else playing = true end
			end
		end
	elseif ofst then
		ofst=ofst*2
		if ofst>64 then ofst=nil end
	end
	Gu.start3d()
		if ofst then
			temp = {{cl4, 90, 236+ofst, 0},{cl4, 90+perc, 236+ofst, 0},{cl5, 90, 252+ofst, 0},{cl5, 90+perc, 252+ofst, 0}}
			Gu.disable(Gu.TEXTURE_2D)
			Gum.drawArray(Gu.TRIANGLE_STRIP, Gu.COLOR_8888+Gu.VERTEX_32BITF+Gu.TRANSFORM_2D, temp)
		end
	Gu.end3d()
	if ofst then screen:blit(0,208+ofst,bar) end
	screen.waitVblankStart()
	screen.flip()
end