back = Image.load("back.png")
cursor = Image.load("cursor.png")
finishImage = Image.load("finish.png")
font = Image.load("font.png")
gameover = Image.load("gameover.png")
guide = Image.load("guide.png")
lesser = Image.load("lesser.png")
tiles = Image.load("tiles.png")
timeImage = Image.load("time.png")
hifont = Image.load("hifont.png")

hack = Sound.load("hack.wav")
miss = Sound.load("miss.wav")
cross = Sound.load("cross.wav")
fanfare = Sound.load("fanfare.wav")

backgroundLayer = Image.createEmpty(480, 272)
numberLayer = Image.createEmpty(480, 272)
linesLayer = Image.createEmpty(480, 272)
finishLayer = Image.createEmpty(480, 272)

function imageRotate(image)
	local w = image:width()
	local h = image:height()
	local result = Image.createEmpty(h, w)
	for x = 0, w-1 do
		for y = 0, h-1 do
			result:pixel(y, w-x-1, image:pixel(x,y))
		end
	end
	return result
end

guide2 = imageRotate(guide)
guide3 = imageRotate(guide2)
guide4 = imageRotate(guide3)

function Controls.waitpadup()
	pad=Controls.read()
	while pad:select() or pad:start() or pad:up() or pad:right() or pad:down() or pad:left() or pad:l() or pad:r() or pad:triangle() or pad:circle() or pad:cross() or pad:square() do
		screen.waitVblankStart()
		pad=Controls.read()
	end
end

function firstDraw()
	backgroundLayer:clear()
	numberLayer:clear()
	linesLayer:clear()

	backgroundLayer:blit(0, 0, back)
	drawHigh(string.format("%02d%02d", math.floor(highscore2/60), math.mod(highscore2,60)))

	for i=1,size do
		for j=1,8 do
			if checkHoriz[i][j]==0 and j~=1 then
				j=9
			else
				drawNumbers(164-((j-1)*12),74+((i-1)*12),checkHoriz[i][j])
			end
		end
		for j=1,8 do
			if checkVert[i][j]==0 and j~=1 then
				j=9
			else
				drawNumbers(176+((i-1)*12),68-(j*9),checkVert[i][j])
			end
		end
	end

	if size>5 then
		linesLayer:drawLine(235, 72, 235, 71+(12*size), orange)
		linesLayer:drawLine(176, 131, 175+(12*size), 131, orange)
	end

	if size>10 then
		linesLayer:drawLine(295, 72, 295, 71+(12*size), orange)
		linesLayer:drawLine(176, 191, 175+(12*size), 191, orange)
	end
end

function drawNumbers(x,y,index)
	numberLayer:blit(x,y,font,12*index,0,12,9)
end

function drawTime(timeString)
	screen:blit(121,19,timeImage,9*tonumber(string.sub(timeString,1,1)),0,9,15)
	screen:blit(132,19,timeImage,9*tonumber(string.sub(timeString,2,2)),0,9,15)
	screen:blit(148,19,timeImage,9*tonumber(string.sub(timeString,3,3)),0,9,15)
	screen:blit(159,19,timeImage,9*tonumber(string.sub(timeString,4,4)),0,9,15)
end

function drawHigh(timeString)
	backgroundLayer:blit(129,46,hifont,7*tonumber(string.sub(timeString,1,1)),0,7,7)
	backgroundLayer:blit(136,46,hifont,7*tonumber(string.sub(timeString,2,2)),0,7,7)
	backgroundLayer:blit(146,46,hifont,7*tonumber(string.sub(timeString,3,3)),0,7,7)
	backgroundLayer:blit(153,46,hifont,7*tonumber(string.sub(timeString,4,4)),0,7,7)
end

function drawRect(x,y)
	screen:blit(x-1,y-1,cursor)
end

function putFinish()
	finishLayer:blit(0, 0, finishImage)
	finishLayer:fillRect(188+math.floor((105-(7*size))/2), 83+math.floor((105-(7*size))/2), 7*size, 7*size, Color.new(255,255,255))
	for i=1,size do
		for j=1,size do
			if board[j][i]==3 then
				finishLayer:fillRect(188+((i-1)*7)+math.floor((105-(7*size))/2), 83+((j-1)*7)+math.floor((105-(7*size))/2), 7, 7, Color.new(56,144,232))
			end
		end
	end
end

function drawFinish(drawLength)
	if drawLength>=0 and drawLength<=480 then
		screen:blit(0, 0, finishLayer,0,0,drawLength,272)
	else
		screen:blit(0, 0, finishLayer)
		if string.len(name)*8<=480 then
			screen:print(((480-(string.len(name)*8))/2),200,name,Color.new(56,144,232))
		else
			screen:print(0,200,name,Color.new(56,144,232))
		end
		screen:print(200,220,"Good Work!",Color.new(0,0,0))
		screen:print(160,240,"Press Select to quit",Color.new(0,0,0))
		if Music.playing() then
			Music.stop()
			fanfare:play()
		end
	end
	screen.waitVblankStart()
	screen.flip()
end

function drawScreen(error)
	screen:clear()

	screen:blit(0,0,backgroundLayer)
	screen:blit(114,60+(dy*12),guide)
	screen:blit(164+(dx*12),10,guide4)
	screen:blit(0,0,numberLayer)

	left=0

	for i=1,size do
		for j=1,size do
			screen:blit(176+((i-1)*12), 72+((j-1)*12), tiles,12*(math.abs(board[j][i])-1), 0, 12, 12)
			if board[j][i]==1 or board[j][i]==2 then
				left=1
			end
		end
	end

	screen:blit(0,0,linesLayer)

	if error~=2 then
		drawRect(175+((dx-1)*12),71+((dy-1)*12))
	end

	if error==1 then
		lessnumber=errors
		if lessnumber>2 then
			lessnumber=2
		end
		screen:blit(184+((dx-1)*12),60+((dy-1)*12),lesser,16*lessnumber,0,16,8)
	end

	if error~=2 then
		timer2=os.time()
	end

	if 1800+os.difftime(timer1,timer2)-errorTime>0 then
		drawTime(string.format("%02d%02d", math.floor((1800+os.difftime(timer1,timer2)-errorTime)/60), math.mod(1800+os.difftime(timer1,timer2)-errorTime,60)))
	else
		drawTime("0000")
		left=-1
	end

	if error~=2 then
		if left==0 then
			if Music.playing() then
				Music.stop()
				Music.playFile("finish.it",true)
			end
		elseif left==-1 then
			if Music.playing() then
				Music.stop()
				Music.playFile("gameover.it",false)
			end
			screen:blit(146, 125, gameover)
			screen:print(158,158,"PRESS SELECT TO QUIT",Color.new(255,255,255))
			screen:print(159,159,"PRESS SELECT TO QUIT",Color.new(0,0,0))
		end

		screen.waitVblankStart()
		screen.flip()
	end
end

function main(directory,filename,oldestcwd)
	Controls.waitpadup()

	dofile(string.format("%s%s",directory,filename))

	illegal=0

	if size==false or board==false or name==false then
		illegal=1
	end

	if illegal==0 then
		for i=1,size do
			for j=1,size do
				if math.abs(board[i][j])<1 then
					illegal=1
				end
				if math.mod(board[i][j],2)==0 then
					board[i][j]=1
				elseif math.mod(board[i][j],2)==1 then
					board[i][j]=-1
				end
			end
		end
	end

	if illegal==1 then
		repeat
			pad = Controls.read()
			screen:clear()
			screen:print(164,124,"WRONG FILEFORMAT!",Color.new(255,0,0))
			screen:print(164,140,"PRESS X TO GO BACK",Color.new(255,0,0))
			screen.waitVblankStart()
			screen.flip()
		until pad:cross()
		return
	end

	highscore1=0
	highscore2=0
	posing1=0
	posing2=0
	posing3=0
	failings=0

	file = io.open(string.format("%s%s%s",directory,filename,".high"), "r")
	if file then
		highscore1 = file:read("*n")
		if file:read(1)~="\x00" and file:read(1)~="\x01" then
			failings=1
		else
			highscore2 = file:read("*n")
			if file:read(1)~="\x00" and file:read(1)~="\x01" then
				failings=1
			else
				posing1 = file:read("*n")
				if file:read(1)~="\x00" then
					failings=1
				else
					posing2 = file:read("*n")
					if file:read(1)~="\x00" then
						failings=1
					else
						posing3 = file:read("*n")
					end
				end
			end
		end
		file:close()
	end
	if failings==1 then
		highscore1=0
		highscore2=0
		posing1=0
		posing2=0
		posing3=0
	end

	posing3=posing3+1

	System.currentDirectory(oldestcwd)

	checkVert = {{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},}

	checkHoriz = {{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},}

	countmax=6
	if size>5 then
		countmax=4
	end

	errors=0
	errorTime=0
	value=0
	value2=0
	temp=0
	left=0

	for i=1,size do
		for j=1,size do
			if board[i][j]==1 then
				value=value+1
			else
				if value>0 then
					for k=1,8 do
						temp=checkHoriz[i][k]
						checkHoriz[i][k]=value
						if temp~=0 then
							value=temp
						else
							k=9
						end
					end
					value=0
				end
			end
			if board[j][i]==1 then
				value2=value2+1
			else
				if value2>0 then
					for k=1,8 do
						temp=checkVert[i][k]
						checkVert[i][k]=value2
						if temp~=0 then
							value2=temp
						else
							k=9
						end
					end
					value2=0
				end
			end
		end
		if value>0 then
			for k=1,8 do
				temp=checkHoriz[i][k]
				checkHoriz[i][k]=value
				if temp~=0 then
					value=temp
				else
					k=9
				end
			end
		end
		value=0
		if value2>0 then
			for k=1,8 do
				temp=checkVert[i][k]
				checkVert[i][k]=value2
				if temp~=0 then
					value2=temp
				else
					k=9
				end
			end
		end
		value2=0
	end

	green = Color.new(0, 255, 0)
	orange = Color.new(248, 160, 0)

	dx=1
	dy=1

	counter=0
	memory=0
	wrong=0

	firstDraw()

	oldPad = Controls.read()

	Music.playFile("picross.it", true)
	timer1=os.time()

	repeat
		pad = Controls.read()

		if pad:circle() and pad:circle()~=oldPad:circle() then
			if math.abs(board[dy][dx])==1 then
				board[dy][dx]=board[dy][dx]*2
				memory=2
				cross:play()
			elseif math.abs(board[dy][dx])==2 then
				board[dy][dx]=board[dy][dx]/2
				memory=1
			else
				memory=0
			end
		end

		if pad~=oldPad or counter==countmax-1 then
			if pad:left() then
				dx=dx-1
				wrong=0
				if dx<1 then
					dx=1
				elseif pad:circle() then
					if math.abs(board[dy][dx])==1 and memory==2 then
						board[dy][dx]=board[dy][dx]*2
						cross:play()
					elseif math.abs(board[dy][dx])==2 and memory==1 then
						board[dy][dx]=board[dy][dx]/2
					end
				end
			elseif pad:right() then
				dx=dx+1
				wrong=0
				if dx>size then
					dx=size
				elseif pad:circle() then
					if math.abs(board[dy][dx])==1 and memory==2 then
						board[dy][dx]=board[dy][dx]*2
						cross:play()
					elseif math.abs(board[dy][dx])==2 and memory==1 then
						board[dy][dx]=board[dy][dx]/2
					end
				end
			elseif pad:up() then
				dy=dy-1
				wrong=0
				if dy<1 then
					dy=1
				elseif pad:circle() then
					if math.abs(board[dy][dx])==1 and memory==2 then
						board[dy][dx]=board[dy][dx]*2
						cross:play()
					elseif math.abs(board[dy][dx])==2 and memory==1 then
						board[dy][dx]=board[dy][dx]/2
					end
				end
			elseif pad:down() then
				dy=dy+1
				wrong=0
				if dy>size then
					dy=size
				elseif pad:circle() then
					if math.abs(board[dy][dx])==1 and memory==2 then
						board[dy][dx]=board[dy][dx]*2
						cross:play()
					elseif math.abs(board[dy][dx])==2 and memory==1 then
						board[dy][dx]=board[dy][dx]/2
					end
				end
			end
		end

		if (pad:cross() and pad:cross()~=oldPad:cross() and wrong==0) or (wrong==0 and pad:cross() and (pad:left() or pad:right() or pad:up() or pad:down())) then
			if math.abs(board[dy][dx])==1 then
				board[dy][dx]=board[dy][dx]*3
				hack:play()
			elseif math.abs(board[dy][dx])==2 then
				board[dy][dx]=board[dy][dx]*1.5
				hack:play()
			end

			if board[dy][dx]==-3 then
				miss:play()
				for i=1,10 do
					drawScreen(1)
				end
				hack:play()
				board[dy][dx]=-2
				drawScreen(1)
				errors=errors+1
				if errors==1 then
					errorTime=120
				elseif errors==2 then
					errorTime=360
				elseif errors==3 then
					errorTime=840
				elseif errors==4 then
					errorTime=1320
				elseif errors==5 then
					errorTime=1800
				end
				wrong=1
			end
		elseif not pad:cross() then
			wrong=0
		end

		drawScreen(0)

		if left<1 then
			if left==0 then
				putFinish()
				drawScreen(2)
				drawFinish(0)
				file = io.open(string.format("%s%s%s",directory,filename,".high"), "w")
				if file then
					if 1800+os.difftime(timer1,timer2)-errorTime > highscore2 and 1800+os.difftime(timer1,timer2)-errorTime < 1800 and 1800+os.difftime(timer1,timer2)-errorTime > 0 then
						if highscore1 == 0 then
							file:write(1800+os.difftime(timer1,timer2)-errorTime.."\x00"..1800+os.difftime(timer1,timer2)-errorTime.."\x00"..posing3.."\x00"..posing3.."\x00"..posing3)
						else
							file:write(highscore1.."\x00"..1800+os.difftime(timer1,timer2)-errorTime.."\x00"..posing1.."\x00"..posing3.."\x00"..posing3)
						end
					else
						file:write(highscore1.."\x00"..highscore2.."\x00"..posing1.."\x00"..posing2.."\x00"..posing3)
					end
					file:close()
				end
				for k=1,121 do
					drawScreen(2)
					drawFinish(k*4)
				end
			elseif left==-1 then
				file = io.open(string.format("%s%s%s",directory,filename,".high"), "w")
				if file then
					file:write(highscore1.."\x00"..highscore2.."\x00"..posing1.."\x00"..posing2.."\x00"..posing3)
					file:close()
				end
			end
			repeat
				screen.waitVblankStart()
				pad = Controls.read()
			until pad:select()
		end

		if oldPad==pad then
			counter = math.mod(counter+1,countmax)
		else
			counter = 0
		end

		oldPad=pad
	until pad:select()
	if Music.playing() then
		Music.stop()
	end
	if left>0 then
		file = io.open(string.format("%s%s%s",directory,filename,".high"), "w")
		if file then
			file:write(highscore1.."\x00"..highscore2.."\x00"..posing1.."\x00"..posing2.."\x00"..posing3)
			file:close()
		end
	end
end

dofile("./browser.lua")

filetypes = {}

filetypes[1]=".mhp"

oldestcwd = System.currentDirectory()
newcwd = System.currentDirectory()
checkDir = {}
checkDir = System.listDirectory(newcwd)
for i=1,table.getn(checkDir) do
	if checkDir[i].directory and string.lower(checkDir[i].name) == "puzzles" then
		System.currentDirectory("./puzzles/")
		newcwd = System.currentDirectory()
	end
end

sorting=1
types=-1
select=1
scroll=0

while true do
	filename, newcwd, sorting, types, select,scroll = browser(filetypes,newcwd,sorting,types, select,scroll)
	if filename==false then
		break
	else
		main(newcwd,filename,oldestcwd)
	end
end
