-- copy all globals into locals, some locals are prefixed with a G to reduce name clashes
local coroutine,package,string,table,math,io,os,debug,assert,dofile,error,_G,getfenv,getmetatable,ipairs,Gload,loadfile,loadstring,next,pairs,pcall,print,rawequal,rawget,rawset,select,setfenv,setmetatable,tonumber,tostring,type,unpack,_VERSION,xpcall,module,require=coroutine,package,string,table,math,io,os,debug,assert,dofile,error,_G,getfenv,getmetatable,ipairs,load,loadfile,loadstring,next,pairs,pcall,print,rawequal,rawget,rawset,select,setfenv,setmetatable,tonumber,tostring,type,unpack,_VERSION,xpcall,module,require


local function print(...) _G.print(...) end

local wstr=require("wetgenes.string")
local pack=require("wetgenes.pack")

--module
local M={ modname=(...) } ; package.loaded[M.modname]=M


local brag="I just matched over {score} bulbs cleaning the wells in #Bulbaceous #PLAY #THE #GAME! http://bulbaceous.com/"

M.bake=function(oven,gui)

	gui=gui or {} 
	gui.modname=M.modname

	gui.pages={} -- put functions to fill in pages in here

	local gl=oven.gl
	local cake=oven.cake
	local sounds=cake.sounds
	local canvas=cake.canvas
	local flat=canvas.flat
	local images=cake.images
	local sheets=cake.sheets

	local wdata=oven.rebake("wetgenes.gamecake.widgets.data")
	local ball=oven.rebake("bulb.ball")
	local bpages=oven.rebake("bulb.pages")
	local bscore=oven.rebake("bulb.score")
	local sgui=oven.rebake("wetgenes.gamecake.spew.gui")
	local sprofiles=oven.rebake("wetgenes.gamecake.spew.profiles")
	local play=oven.rebake("bulb.game_play")
	local coins=oven.rebake("bulb.coins")
	local levels=oven.rebake("bulb.levels")
	local sscores=oven.rebake("wetgenes.gamecake.spew.scores")
	local beep=oven.rebake("bulb.beep")
	local score=oven.rebake("bulb.score")
	local menu=oven.rebake("bulb.game_menu")

	local about=oven.rebake("wetgenes.gamecake.spew.about.sinescroll")

	about.title="Dr Bulbaceous : Puzzle Solver"
	about.text=[[
*SKIP*
Welcome to the wonderful world of Dr Bulbaceous.
*SKIP*
As you play your cookie jar will fill up, see the number at the lower right for how many cookies you currently have.
*SKIP*
Don't be scared to spend your cookies as they will be returned to you at the start of your next game.
*SKIP*
So if you get into trouble just swap your bulbs for better ones.
*SKIP*
However for maximum score the trick is not to spend any cookies at all.
*SKIP*
]]

--[[
A puzzling arcade experience. Descend through 100 levels of challenging puzzle mayhem in a quest to defeat the big bad boss at the bottom of the bottom most well. Use bonus balls for easy victory or restrain yourself for maximum score. Lead on bold adventurer the choice is yours.
]]


	about.playtune=function()
		beep.stream("about")
	end
	about.exitname="bulb.game"

	gui.fbos={}
	gui.sheets={}

	function gui.spage(pname)

		sgui.strings.brag=brag

		sgui.beep_hook=beep
		sgui.page_hook=gui.page
		sgui.widget_hook=function(w)
			if w.id=="score_block" then
				w.sheet="scoreboard"
				w.color=0xffffffff
				w.hooks={}
			end
			if w.id=="score_title" then
				w.sheet="scorebanner"
				w.color=0xffffffff
				w.hooks={}
			end
			if w.id=="score_title_text" then
				w.color=nil
				w.text=nil
				w.hooks=nil
			end
			if w.id=="score_part" then
				w.color=nil
				w.hooks=nil
			end
			bpages.widget_anim(w)
		end
		if pname then
			gui.page("menu")
			sgui.page(pname)
		end
	end

	function gui.setup()
		gui.page()
		sgui.setup() -- setup sub gui
		gui.spage()
	end
	
	gui.ids={}
	gui.data={}
	gui.data.modes={
						{title="Endurance",talk="Play forever, or until you die."} ,
						{title="Daily Puzzle",talk="Compete once a day on a puzzle."}
					}--, "Sixty Seconds"}
	gui.data.mode=1
	
	function gui.set_all_values()
		local ids=gui.master.ids
		local d=gui.data
--		if ids.menu_gamemode then ids.menu_gamemode.text=d.modes[d.mode].title end
	end
	
	function gui.hooks(act,widget)
		local ids=gui.master.ids
		local d=gui.data
		local id=widget and widget.id
		local user=widget and widget.user
		
	local qq={}--sounds.queues[2]
	qq.state="play_queue"
	qq.voice={
		
	}
	
		if act=="over" then bpages.widget_anim(widget,1/16) end

		if act=="click" then
--print("click",id)

			if id=="game_menu_continue" then
				beep.play("button3")
				play.pause=false
			end

			if id=="game_menu_stop" then
				beep.play("button3")
				gui.page("game_menu_stop")
			end
			if id=="game_menu_exit" then
				gui.page("game_menu_exit")
			end
				
			if id=="game_menu_stop_stop" then
				beep.play("button3")
				oven.game.next=menu
			end
			if id=="game_menu_exit_exit" then
				oven.next=true -- really quit
				gui.page("menu")
			end

				
			if id=="menu_hello" then
				beep.play("button3")
				gui.spage("profiles")
			end
			if id=="menu_quit" then
				beep.play("button3")
				gui.spage("quit")
			end
			if id=="menu_settings" then
				beep.play("button2")
--				qq.talks={"Do you want to kwit the game.",}
				gui.spage("settings")
			end
			if id=="quit_return" then
				qq.talks={"Ha ha humanoid. Ha ha intrudeer.",}
				gui.page("menu")
			end
			if id=="quit_exit" then
				qq.talks={"Good bye sweet world.",}
				oven.next=true
			end
			if id=="menu_play" then
				beep.play("button1")
				gui.page("shop_levels")
--				qq.talks={"Beware koward. I Liv.",}
--				state.game.next=play
--				play.setup_mode{mode="endurance",level=1}
			end
			if id=="level_play" then
				beep.play("button1")
				oven.game.next=play
				play.setup_mode{mode="puzzle",level=user}
			end
			if id=="menu_gamemode" then
				d.mode=d.mode+1
				if d.mode > #d.modes then d.mode=1 end
				gui.set_all_values()
				qq.talks={d.modes[d.mode].talk}
				gui.page("levels")
			end
			if		id=="score_brag" then
				beep.play("button2")
				beep.stream("menu")
				sgui.hooks(act,widget)
			elseif	id=="score_list" then
				beep.play("button1")
				beep.stream("menu")
				sgui.hooks(act,widget)
			elseif	id=="menu" then
				beep.play("button1")
				beep.stream("menu")
				gui.page("menu")
			end
		end
	
	end

	function gui.pages.score(master)
	
		beep.stream("score")

		local top=master:add({hx=320,hy=480,class="abs",font="ostrich-black",text_size=24})

		for i,v in ipairs{
			{
				name="score00",
			},
			{
				name="score01",
				id="score_lift",
				py=-512,
			},
			{
				name="score02",
			},
			{
				name="score05",
				id="score_numbers",
			},
			{
				name="score06",
			},
			{
				name="score08",
				id="score_brag",
				hooks=gui.hooks,
			},
			{
				name="score09",
				id="menu",
				hooks=gui.hooks,
			},
		} do
		
			local skip=false
			if v.id=="score_brag" then
				if oven.opts.smell=="gamestick" then -- hide brag button
					skip=true
				end
			end
			
			if not skip then
				local o={}
				local img=images.get(v.name)
				
				o.px=(img.meta.x/2) -512 + 160
				o.py=(img.meta.y/2) -256 + 240
				o.hx=img.meta.w/2
				o.hy=img.meta.h/2
				
				o.id=v.id
				o.hooks=v.hooks
				o.sheet=v.name
	--			o.text=v.name
				
	--			o.sheet_id=1
				o.sheet_px=o.hx/2 + (v.px or 0)
				o.sheet_py=o.hy/2 + (v.py or 0)
				o.sheet_hx=o.hx
				o.sheet_hy=o.hy

				o.color=0xffffffff
				
				if not o.hooks then o.highlight="none" end

	--print(wstr.dump(o))			

				top:add(o)
			end
		end

		local gainc=coins.gain -- how many coins gained this play
		local numc=coins.num -- how many coins we have
		
		local eff=(coins.num-coins.gain) -- started with
		if eff<1 then eff=1 end
		eff=math.floor((coins.gain/eff)*100)
		if eff<1 then eff=1 elseif eff>100 then eff=100 end -- so 100% effort is doubling our coins

		local score=sscores.up[1].score
		local best=sscores.list({})[1]			best=(best and best.score) or 0
		local mine=sscores.get_best_score({})	mine=(mine and mine.score) or 0
		if best<score then best=score end
		if mine<score then mine=score end
		
		local top_pct=math.floor((1-(score/best))*100)
		if top_pct<1 then top_pct=1 elseif top_pct>100 then top_pct=100 end

--print("best",best)
--print("score",score)
--print("top",top_pct)

		local best_pct=0
		local mine_pct=0
		if best<1 then best_pct=0 else best_pct=math.floor(100*score/best) end
		if mine<1 then mine_pct=0 else mine_pct=math.floor(100*score/mine) end
		
		local rank=sgui.offset or 0
		
		top:add{px=70,py=70-4 ,hx=210,hy=30,text="",id="score_rank",text_color=0xffffffff}
		top:add{px=70,py=235,hx=210,hy=30,text="",id="score_num"}

		top:add{px=70,py=320-4,hx=210,hy=30,text="",id="score_found",text_color=0xff8e3ab7}
		top:add{px=70,py=350-4,hx=210,hy=30,text="",id="score_suck" ,text_color=0xffff0066}

		
		local base_py1=gui.master.ids["score_lift"].py
		local base_py2=gui.master.ids["score_numbers"].py
--		local max_py=150
		local my=play.level*10 if my<=0 then my=1 end
		local y=0
		local pc=0
		
		my=175
		
		local finished
		
		gui.update_anim=function()
			if y<my then
				y=y+2
			else
				y=my
				if not finished then
					finished=true
					beep.play("score4")
				end
			end
			
			pc=y/my				

			local v=gui.master.ids["score_lift"]
			v.py=base_py1+y

			local v=gui.master.ids["score_numbers"]
			v.py=base_py2+175-(play.level*10*pc)

			local v=gui.master.ids["score_rank"]
			local n=math.ceil( rank+1000*(1-pc) )
			v.text="You are "..wstr.str_append_english_number_postfix(n).."!"
			local n=100-math.ceil( (100-top_pct)*pc )
			v.text="You're in the top "..top_pct.."%!"

			local v=gui.master.ids["score_num"]
			local n=math.ceil(score*pc)
			v.text=wstr.str_insert_number_commas(n)

			local v=gui.master.ids["score_found"]
			local n=math.ceil(gainc*pc)
			v.text="Found "..wstr.str_insert_number_commas(n).."c"

			local v=gui.master.ids["score_suck"]
			local n=math.ceil(eff*pc)
			v.text=n.."% Success!"

		end

		gui.master.go_forward_id="menu"
		
	end
		
	function gui.pages.play(master)

		
	end
	

	function gui.pages.menu(master)
	

		beep.stream("menu")

		coins.setup()

		local top=master:add({hx=320,hy=480,class="abs",font="ostrich-black",text_size=24})
		bpages.add(top,"menu")
		
		local n=sprofiles.get("name")
		local g=gui.master.ids.menu_hello
		if g then
			g:add({px=110,py=12,text=n,text_size=10})
		end
		
		gui.master.go_forward_id="menu_play"
		
	end


	local function gui_pages_shop(master,show)

		local add9x9,idx
		
		beep.stream("shop")

		local top=master:add({hx=300,hy=300,px=10,py=120,class="fill",font="ostrich-black"})

		local hooks=function(act,w)
			if act=="over" then bpages.widget_anim(w,1/16) end
			if act=="click" then
				if w.id and w.id:sub(1,5)=="level" then

					local u=w.user
					if u then
						play.butt_wait=10
						play.pause=false -- hide
						coins.pspend(u.price)
						oven.game.next=play
						play.setup_mode{
							mode="puzzle",
							level=u.level
						}
						sprofiles.set("start_level",u.level)
					end
					
				elseif w.id and w.id:sub(1,4)=="ball" then
--print("BUTTWAIT")
					play.butt_wait=10
					play.pause=false -- hide
					ball.id=w.sheet_id
					w.user:buy()
					if beep.replay then beep.stream("play") end
					score.levelstr(w.user.popup)

				elseif     w.id=="next" then

					idx=idx+9
					add9x9(idx)

				elseif w.id=="back" then

					idx=idx-9
					add9x9(idx)
					
				elseif w.id=="shop_exit" then
--print(w.id)				
					if show=="balls" then
						play.pause=false
						if beep.replay then beep.stream("play") end
					else
						oven.game.next=menu
					end

				end
			end
		end
		

		local x9=top:add({hx=300,hy=300,class="fill"})
		add9x9=function()

			if idx>100-9 then idx=100-9 end
			if idx<1 then idx=1 end
				
			if show=="balls" then
				if idx>#coins.buys-8 then idx=#coins.buys-8 end
			end
			
			x9:clean_all()

			local ii=1
			for i=idx,idx+8 do
		
				if show=="balls" then
				
					local b=coins.buys[i]
					local s=x9:add({hx=100,hy=100})
					if b then
						local price=b:price()
						local color=0xffffffff
						local hooks=hooks
						if not coins.affordable( price ) then color=0xff880000 hooks=nil end
						if ball.state_name~="swing" or ball.sx~=1 then color=0xff880000 hooks=nil end -- wait for a safe time
						s:add({hx=100,hy=70,color=color,
							sheet="bulbs",sheet_id=b.id,sheet_px=50,sheet_py=50,sheet_hx=50,sheet_hy=50,hooks=hooks,id="ball"..i,user=b})
						s:add({hx=100,hy=30,py=70,text=wstr.str_insert_number_commas(price).."c",text_color=0xffffffff,text_color_shadow=0xff000000,text_size=16})
					end
					
				else

			
			
					local w=sprofiles.get("won_"..i) or 0
					local s=x9:add({hx=100,hy=100})
					if i<=100 and i>=1 then

						gui.fbos[ii]=levels.fbo_wrap(gui.fbos[ii],function() levels.fbo_draw(i) end)

						local price=coins.level_price(i)
						local color=0xffffffff
						local lbas="butt_level0"
						local lovr
						if w==3 then lovr="butt_level3"
						elseif w==2 then lovr="butt_level2"
						elseif w==1 then lovr="butt_level1"
						end
						local hooks=hooks
						if not coins.affordable( price ) then --[[color=0xff880000]] lbas="butt_level" hooks=nil end
						local b=s:add({hx=100,hy=100,color=color,id="level"..i,hooks=hooks,user={level=i,price=price},text_size=16})
							b.draw=
							function(w)
								w:draw_base(function(w)
									for layer in w:iterate_draw_color() do
										cake.sheets.get(lbas):draw(1,50,50,0,100,100)
									end
	--								if lovr then
	--									cake.sheets.get(lovr):draw(1,50,50,0,100,100)
	--								end
								end)
							end	
	--					b:add{hx=((3-w)*20),hy=25,px=40,py=45,color=0xff000000}
	--					b:add{hx=60,hy=20,px=40,py=50,text=("#"):rep(w)..("-"):rep(3-w)}
						--if w>0 then -- only draw the level if it has been beat
						if coins.affordable( price ) then
							b:add{hx=100,hy=64,px=24,py=0,user=ii}.draw=function(w)
								w:draw_base(function(w)
									gl.Color(1/2,1/2,1/2,1/2)
									gl.BindTexture(gl.TEXTURE_2D, gui.fbos[w.user].texture)
									flat.tristrip("xyzuv",{
										0,		0,		0,		0,	1,
										64,		0,		0,		1,	1,
										0,		60,		0,		0,	0,
										64,		60,		0,		1,	0,
									})							
								end)
							end
						else
	--						b:add{hx=55,hy=70,px=0,py=0,user=ii,text="?",text_color=0xffffffff,text_size=32}
						end
		--				s:add({hx=100,hy=30,text="00",text_color=0xffffffff,text_color_shadow=0xff000000,text_size=16,hooks=hooks,user={level=i,price=price}})	

						if lovr then
							local b=s:add({hx=100,hy=100,color=0xffffffff})
							b.draw=function(w)
								w:draw_base(function(w)
									for layer in w:iterate_draw_color() do
										cake.sheets.get(lovr):draw(1,50,50,0,100,100)
									end
								end)
							end
						end	

						b:add{hx=60,hy=50,px=20,py=12,text=("%02d"):format(i),text_color=0xffffffff,text_color_shadow=0xff000000,text_size=16}

						b:add({hx=100,hy=30,py=75,text=wstr.str_insert_number_commas(price).."c",text_color=0xffffffff,text_color_shadow=0xff000000,text_size=16})	

					end
					
				end
				
				ii=ii+1
			end
			
			top:layout()
			
			gui.master:call_descendents(function(w) bpages.widget_anim(w) end)
			if gui.master.over and gui.master.over.id then
				gui.master.activate_by_id(gui.master.over.id)
			end
		end
		
		idx=1
		if show=="levels" then
			idx=( sprofiles.get("start_level") or 1 )
			gui.master.go_forward_id="level"..idx
		else
			gui.master.go_forward_id="shop_exit"
		end
		gui.master.go_back_id="shop_exit"
		

		top:add({hx=100,hy=50,color=0xffffffff,id="back",hooks=hooks}).draw=
			function(w)
				w:draw_base(function(w)
					for layer in w:iterate_draw_color() do
						cake.sheets.get("butt_popleft"):draw(1,w.hx/2,w.hy/2,0,98/2,88/2)
					end
				end)
			end						

		top:add({hx=100,hy=50,color=0xffffffff,id="shop_exit",hooks=hooks}).draw=
			function(w)
				w:draw_base(function(w)
					for layer in w:iterate_draw_color() do
						cake.sheets.get("butt_popback"):draw(1,w.hx/2,w.hy/2,0,88/2,94/2)
					end
				end)
			end						

		top:add({hx=100,hy=50,color=0xffffffff,id="next",hooks=hooks}).draw=
			function(w)
				w:draw_base(function(w)
					for layer in w:iterate_draw_color() do
						cake.sheets.get("butt_popright"):draw(1,w.hx/2,w.hy/2,0,98/2,88/2)
					end
				end)
			end						

		add9x9()


	end

	function gui.pages.shop_balls(master)
		return gui_pages_shop(master,"balls")
	end

	function gui.pages.shop_levels(master)
		return gui_pages_shop(master,"levels")
	end


	function gui.pages.game_menu_stop(master)

		local top=master:add({hx=320,hy=480,class="fill",font="Vera",text_size=24})

		top:add({hx=320,hy=40*5})

		top:add({hx=320,hy=30*1,text_color=0xffffffff,text="Are you sure you want"})
		top:add({hx=320,hy=30*1,text_color=0xffffffff,text="to stop playing?"})

		top:add({hx=320,hy=40})

		top:add({hx=20,hy=30*2})
		top:add({hx=280,hy=30*2,color=0xffcccccc,text="Keep playing.",id="game_menu_continue",hooks=gui.hooks})
		top:add({hx=20,hy=30*2})

		top:add({hx=320,hy=10})

		top:add({hx=20,hy=30*2})
		top:add({hx=280,hy=30*2,color=0xffcccccc,text="Stop playing.",id="game_menu_stop_stop",hooks=gui.hooks})
		top:add({hx=20,hy=30*2})

		top:add({hx=320,hy=10})

		top:add({hx=320,hy=40})
		
		master.go_back_id="game_menu_continue"
		master.go_forward_id="game_menu_continue"

	end

	function gui.pages.game_menu_exit(master)

		local top=master:add({hx=320,hy=480,class="fill",font="Vera",text_size=24})

		top:add({hx=320,hy=40*5})

		top:add({hx=320,hy=30*1,text_color=0xffffffff,text="Are you sure you want"})
		top:add({hx=320,hy=30*1,text_color=0xffffffff,text="to exit the game?"})

		top:add({hx=320,hy=40})

		top:add({hx=20,hy=30*2})
		top:add({hx=280,hy=30*2,color=0xffcccccc,text="Keep playing.",id="game_menu_continue",hooks=gui.hooks})
		top:add({hx=20,hy=30*2})

		top:add({hx=320,hy=10})

		top:add({hx=20,hy=30*2})
		top:add({hx=280,hy=30*2,color=0xffcccccc,text="Exit Game.",id="game_menu_exit_exit",hooks=gui.hooks})
		top:add({hx=20,hy=30*2})

		top:add({hx=320,hy=10})

		top:add({hx=320,hy=40})
		
		master.go_back_id="game_menu_continue"
		master.go_forward_id="game_menu_continue"

	end

	function gui.pages.game_menu(master)

		local top=master:add({hx=320,hy=480,class="fill",font="Vera",text_size=24})

		top:add({hx=320,hy=40*5})

		top:add({hx=20,hy=30*2})
		top:add({hx=280,hy=30*2,color=0xffcccccc,text="Keep playing.",id="game_menu_continue",hooks=gui.hooks})
		top:add({hx=20,hy=30*2})

		top:add({hx=320,hy=10})

		top:add({hx=20,hy=30*2})
		top:add({hx=280,hy=30*2,color=0xffcccccc,text="Stop playing.",id="game_menu_stop",hooks=gui.hooks})
		top:add({hx=20,hy=30*2})

		top:add({hx=320,hy=10})

		top:add({hx=20,hy=30*2})
		top:add({hx=280,hy=30*2,color=0xffcccccc,text="Exit Game.",id="game_menu_exit",hooks=gui.hooks})
		top:add({hx=20,hy=30*2})

		top:add({hx=320,hy=10})

		top:add({hx=320,hy=40})
		
		master.go_back_id="game_menu_continue"
		master.go_forward_id="game_menu_continue"

	end
	
	function gui.page(pname)
		local ret=false
		
		gui.update_anim=nil
		
		if not gui.master then
			gui.master=oven.rebake("wetgenes.gamecake.widgets").setup({hx=320,hy=480})
		end
	
		gui.master:clean_all()
		gui.master.ids={}
		gui.default_widget=nil
		gui.default_id=nil
		
		if pname then
			local f=gui.pages[pname]
			if f then
				f(gui.master) -- pass in the master so we could fill up other widgets
				ret=true
			end
		end

		gui.page_name=pname
		
		gui.set_all_values()

		gui.master:layout()
		
		gui.master:call_descendents(function(w) bpages.widget_anim(w) end)

		if gui.master.go_forward_id then
			gui.master.activate_by_id(gui.master.go_forward_id)
		end

		return ret
	end

	function gui.clean()

		gui.master=nil
	
	end
	
	function gui.update()
	
		if gui.update_anim then gui.update_anim() end
	
		bpages.update()
	
		gui.master:update()

	end
	
	function gui.msg(m)

		gui.master:msg(m)

	end

	function gui.draw()
	
		gui.master:draw()

	end
	
	return gui
end
