local params = {}

local SIZE = 256
local SPACING = SIZE / 16

local noise_1 = Material("effects/tvscreen_noise001a.vmt")
local noise_2 = Material("effects/tvscreen_noise002a.vmt")
local background = Material("fishing_mod/inventory.png")
local top = Material("fishing_mod/inventory_top.png")
local arrow = fishing.GetMaterialFromURL("http://dl.dropbox.com/u/244444/pokemon_arrow.png", 32)
local noise_sound
local last = 0
local last_model = ""
local white = Material("models/debug/debugwhite")
local selected_i = 1
local last_select = 0
local scroll = 0
local page = 0
local cs_model = NULL 

surface.CreateFont(
	"fishing_inventory_font",
	{
		font 		= "Trebuchet",
		size 		= 13,
		weight 		= 550,
		antialias = false,
	}
)

local function can_draw()
	if last > SysTime() then
		return false
	end

	last = SysTime() + 1/15

	return true
end

local function draw_text(x, y, str, r,g,b,a, a2)
	surface.SetFont("fishing_inventory_font")
	
	surface.SetTextPos(x+1, y+1)
	surface.SetTextColor(0,0,128,a2 or 80)
	surface.DrawText(str)

	surface.SetTextColor(r or 20,g or 40, b or 80, a or 255)
	surface.SetTextPos(x, y)
	surface.DrawText(str)
end

local cam_ang = Angle()

local function draw_camera(ent, wep)
	local ply = wep.Owner
	local pos = ent:GetPos()
	local ang = (ent:GetAngles():Up()*-1):Angle()
	local dir = (ply:EyePos() - ent:GetPos()):GetNormalized()
		
	local ft = FrameTime()
	
	if input.IsKeyDown(KEY_DOWN) then
		cam_ang.p = cam_ang.p + ft * 100
	elseif input.IsKeyDown(KEY_UP) then
		cam_ang.p = cam_ang.p + ft * -100
	end
	
	if input.IsKeyDown(KEY_LEFT) then
		cam_ang.y = cam_ang.y + ft * 100
	elseif input.IsKeyDown(KEY_RIGHT) then
		cam_ang.y = cam_ang.y + ft * -100
	end
	
	dir:Rotate(cam_ang)
	
	pos = pos + dir * 50

	params.origin = pos
	params.angles = (dir*-1):Angle()

	params.fov = 90
	params.x = 0
	params.y = 0
	params.w = SIZE
	params.h = SIZE

	params.znear = 0.1

	pac.ForceRendering(true)
		render.RenderView(params)
	pac.ForceRendering(false)

	surface.SetFont("fishing_inventory_font")

	local max_tension = fishing.GetStats(ply).string_max_tension or 4
	local str = string.format("length = %i\ttension = %i/%i", wep.dt.length, fishing.LineTension*100, max_tension * 100)
	local w,h = surface.GetTextSize(str)

	surface.SetDrawColor(255, 255, 255, 255)
	surface.SetMaterial(top)
	surface.DrawTexturedRect(0,0, SIZE,SIZE)

	draw_text(4,0,str)

	surface.SetMaterial((wep.dt.snapped or fishing.LineTension > 20) and noise_1 or noise_2)
	surface.SetDrawColor(0, 255, 0, (fishing.LineTension - 1) * 255)
	surface.DrawTexturedRect(0, 0, SIZE, SIZE)
end

local function calc_sound(ply, wep, ent)
	if wep.dt.length > 1 and fishing.ScreenFocus then
		if not noise_sound then
			--noise_sound = CreateSound(ply, "ambient/gas/steam2.wav")
			--noise_sound:SetSoundLevel(80)
		end

		local length = fishing.GetStats(ply).rod_length or 1
		local pos = ply:EyePos() + ply:GetForward() * 140 * length
		local tension = wep.dt.hook:GetPos():Distance(pos) / wep.dt.length

		if wep.dt.length < 40 then
			tension = tension / 100
		end
		
		fishing.LineTension = tension

		if tension > 1.12 or wep.dt.snapped then
			local vol = math.Clamp(tension/20, 0, 1) ^ 2

			if vol == 0 then
				--noise_sound:Stop()
			else
			--	noise_sound:PlayEx(vol, 50+math.sin(os.clock()))
			end
		end
	end
end

local function calc_keys(i)
	if last_select < os.clock() then
		if input.IsKeyDown(KEY_LEFT) then

			last_select = os.clock() + 0.1
			LocalPlayer():EmitSound("weapons/sniper/sniper_zoomin.wav", 50, 140)
		elseif input.IsKeyDown(KEY_RIGHT) then

			last_select = os.clock() + 0.1
			LocalPlayer():EmitSound("weapons/sniper/sniper_zoomin.wav", 50, 140)
		end

		if input.IsKeyDown(KEY_UP)then
			selected_i = selected_i - 1
			
			last_select = os.clock() + 0.1
			LocalPlayer():EmitSound("buttons/blip1.wav", 30, 255)
		elseif input.IsKeyDown(KEY_DOWN) then
			selected_i = selected_i + 1
			
			last_select = os.clock() + 0.1
			LocalPlayer():EmitSound("buttons/blip1.wav", 30, 255)
		end
		
	end
end

local function draw_inventory(ply, wep, ent)
	render.ClearDepth()

	surface.SetDrawColor(255, 255, 255, 250)
	surface.SetMaterial(background)
	surface.DrawTexturedRect(0, 0, SIZE, SIZE)

	surface.SetFont("fishing_inventory_font")
	local w = surface.GetTextSize("INVENTORY")
	draw_text(SIZE / 2 - w/2,SPACING-5, "INVENTORY")

	local items = fishing.GetPlayerInventorySorted()

	if items then
		local current_height = SPACING * 3
		local count = 0

		for _i=1, #items do
			local data = items[_i + scroll]

			if not data then continue end
			
			-- get the meta table which holds some info like name and description
			local class = fishing.RegisteredBait[data.name] or fishing.RegisteredFish[data.name]
			local name = class and class.Name or data.name
			
			-- draw its name
			local w,h = surface.GetTextSize(name)
			draw_text(SPACING * 2, current_height, name)
			
			-- the x
			local w,h = surface.GetTextSize("x")
			draw_text(SIZE - SPACING*3 - w, current_height, "x")
			
			-- count
			local w,h = surface.GetTextSize(data.count)
			draw_text(SIZE - SPACING*1.5 - w, current_height, data.count)			

			local height = SIZE - SPACING * 4

			if selected_i == count then				
				-- if it 's selected, draw an arrow on it
				local w,h = surface.GetTextSize(">")
				draw_text(SPACING, current_height, ">")
				
				-- draw the description
				surface.SetTextColor(255, 255, 255, 255)
				
				local description = class and class.Description or "??????????????????????\n??????????????????????\n??????????????????????"
				local mdl = class and class.Model or "models/error.mdl"
				
				local last_h = height
				for _, line in pairs(description:Split("\n")) do
					local w, h = surface.GetTextSize(line)
					draw_text(SPACING * 4.2, last_h + SPACING/3, line, 255, 255, 255, 255, 128)
					last_h = last_h + h
				end

				-- draw the model				
				if mdl ~= last_model then
					-- check if the model changed first
					if not cs_model:IsValid() then
						cs_model = ClientsideModel(mdl)
						cs_model:SetNoDraw(true)
					else
						cs_model:SetModel(mdl)
					end
					last_model = mdl
				end
				
				local center = cs_model:OBBCenter()
				local pos = Vector(1,1,1) * (cs_model:BoundingRadius() * 100)
				local ang = (center - pos):Angle()

				render.SuppressEngineLighting( true )
					cam.IgnoreZ(true)
					
						for i = 1, 2 do
							cam.Start3D(pos, ang, i == 1 and 0.9 or 1, 8, SIZE - 50, 50,35)
								if i == 1 then
									render.MaterialOverride(white)
									render.SetColorModulation(0.25, 0.25, 0.25)
								else
									render.MaterialOverride()
									render.SetColorModulation(1,1,1)
								end
								cs_model:SetAngles(Angle(0,SysTime() * -50,0))
								cs_model:DrawModel()
							cam.End3D()

							render.ClearDepth()
						end
						
					cam.IgnoreZ(false)
				render.SuppressEngineLighting(false)
			end

			count = count + 1

			-- don't draw more if it reached the bottom of the white area
			if current_height + h + SPACING * 6 > SIZE then
				break
			else
				current_height = current_height + h
			end
		end

		calc_keys(count)

		selected_i = math.Clamp(selected_i, -1, count)
			
		if count == selected_i then
			selected_i = selected_i - 1 
			scroll = scroll + 1
		end
		
		if selected_i < 0 then
			scroll = scroll - 1
			selected_i = selected_i + 1 
		end
		
		scroll = math.Clamp(scroll, 0, count)
	end
end

local crashed_smiley = Material("fishing_mod/crashed.png")
local error_msg = 
{
	"Aw, Snap!",
	"",
	"Your string snapped while using this rod.",
	"To continue, reselect this rod or use ",
	"another weapon.",
}

local function draw_snapped()
	surface.SetDrawColor(35, 48, 64, 255)
	surface.DrawRect(0,0, SIZE, SIZE)
	
	surface.SetDrawColor(255, 255, 255, 255)
	local x, y = SIZE / 2 - 32, SIZE / 2 - 32
	surface.SetMaterial(crashed_smiley)
	surface.DrawTexturedRect(x, y, 62,62)
	
	local height = SPACING * 4
	
	for i, line in pairs(error_msg) do
		local w, h = surface.GetTextSize(line)
		draw_text(x - w*0.5 + 32, y + height + h * i, line, 255, 255, 255, 255)
	end
end

local function draw_screen(ply, wep, ent)
	if wep.dt.snapped then
		draw_snapped()
	else
		if wep.dt.length > 1 then
			draw_camera(ent, wep)
		else
			draw_inventory(ply, wep, ent)
		end

		calc_sound(ply, wep, ent)
	end
end

hook.Add("Think", "fishing", function()
	if not fishing.IsFishing() then
		selected_i = 1
		last_select = 0
		scroll = 0
	return end

	if not can_draw() then return end
	
	local ply = LocalPlayer()
	local wep = ply:GetActiveWeapon()
	local ent = wep.dt.hook

	if not ent:IsValid() then return end

	if not fishing.RTTexture then		
		fishing.RTTexture = GetRenderTarget("fishing_RT", SIZE, SIZE, false)
		fishing.RTMaterial = CreateMaterial("fishing_rt_mat", "VertexLitGeneric", {})
		fishing.RTMaterial:SetTexture("$basetexture", fishing.RTTexture)
	end
	
	local old, w, h = render.GetRenderTarget(), ScrW(), ScrH()

	render.SetRenderTarget(fishing.RTTexture)
		render.Clear(0, 0, 0, 255, false)
		render.SetViewPort(0, 0, SIZE, SIZE)
			cam.Start2D()
				draw_screen(ply, wep, ent)
			cam.End2D()
		render.SetViewPort(0, 0, w, h)
	render.SetRenderTarget(old)
end)

hook.Add("PlayerBindPress", "fishing", function(ply, bind, press)
	if press and fishing.IsFishing(ply) then
		if bind == "+use" then
			local item = fishing.GetPlayerInventorySorted()[selected_i+scroll+1]

			if item then
				RunConsoleCommand("fishing_pickup_item", item.name)
			else
				RunConsoleCommand("fishing_pickup_item")
			end
			return true
		elseif bind == "undo" then
			RunConsoleCommand("fishing_pickup_item")
			return true
		elseif bind == "+reload" then
			RunConsoleCommand("fishing_release_item")
			return true
		elseif bind == "+menu" then
			fishing.ScreenFocus = not fishing.ScreenFocus
			return true
		end
	end
end)