local otrx_range = CV_FindVar("otrx_range")
local otrx_spb_range = CV_FindVar("otrx_spb_range")
local OR_GetSplitscreenCoords = OR_GetSplitscreenCoords
local OR_GetOTricksIconCoords = OR_GetOTricksIconCoords

local function OpenTricks_GetFivePatches(index)
  local indices = {index - 2, index - 1, index, index + 1, index + 2}
  if #OpenTricks_Table == 1
	return {1, 1, 1, 1, 1}
  end
  for key, value in pairs(indices)
    local x = value
	
    while x > #OpenTricks_Table do
      x = $ % #OpenTricks_Table
    end
	
    while x < 1 do
      x = #OpenTricks_Table + x
    end
	
    indices[key] = x
  end
  return indices
end

local function OpenTricks_Drawer(othud, player, cam)
  if (OpenTricks_GetRange(player, false) == 0)
    return
  end
  
  if not player.OpenTricks or not OpenTricks_Table
    return
  end
  
  -----------------------
  -- prepare variables --
  -----------------------
  
  local onPatches, offPatches = {}, {}
  local cursor_patch = othud.cachePatch("TRXCRSR")
  local left_patch = othud.cachePatch("TRXSEL_L")
  local right_patch = othud.cachePatch("TRXSEL_R")
  local meter_cursor = othud.cachePatch("TRXSEL_L")
  
  local onPatches, offPatches, chosenPatches, chosenSmallPatches = {}, {}, {}, {}
  
  for key,style in pairs(OpenTricks_Table)
    onPatches[style.name] = othud.cachePatch(style.onIcon)
	offPatches[style.name] = othud.cachePatch(style.offIcon)
	chosenPatches[style.name] = othud.cachePatch(style.chosenIcon)
	chosenSmallPatches[style.name] = othud.cachePatch(style.chosenIconSmall)
  end
  
  local mobj = player.mo
  
  local screen_width, screen_height, hori_center, vert_center = OR_GetSplitscreenCoords(cam)
  
  local meter_x, meter_y = hori_center, vert_center
  
  if mobj and mobj.valid
    meter_x, meter_y = R_GetScreenCoords(othud, player, cam, mobj.x, mobj.y, mobj.z)
  end
  
  meter_y = max($, 60<<FRACBITS)
  meter_y = min($, 200<<FRACBITS) -- clamp vertical position for cases like Blue Mountain's intro
  
  local icon_x, icon_y = OR_GetOTricksIconCoords(cam)
  
  ---------------------------------
  -- draw selection or trick hud --
  ---------------------------------
  
  if OpenTricks_CanSelect(player)
    local cur = player.OpenTricks.trick_number
    local reel = OpenTricks_GetFivePatches(cur)
	local numbered_patches = {offPatches[OpenTricks_Table[reel[1]].name],
	                          offPatches[OpenTricks_Table[reel[2]].name],
							  onPatches[OpenTricks_Table[reel[3]].name],
							  offPatches[OpenTricks_Table[reel[4]].name],
							  offPatches[OpenTricks_Table[reel[5]].name]}
    
    othud.draw(hori_center - 40, vert_center - 3, numbered_patches[1], V_40TRANS)
    othud.draw(hori_center + 40, vert_center - 3, numbered_patches[5], V_40TRANS)
    othud.draw(hori_center - 20, vert_center - 1, numbered_patches[2], V_20TRANS)
    othud.draw(hori_center + 20, vert_center - 1, numbered_patches[4], V_20TRANS)
    othud.draw(hori_center,      vert_center,     numbered_patches[3])

    othud.draw(hori_center, vert_center, cursor_patch)
	
	othud.draw(hori_center - 52 - (leveltime / 5 % 2), vert_center, left_patch)
	othud.draw(hori_center + 52 + (leveltime / 5 % 2), vert_center, right_patch)
	
    othud.drawString(hori_center, vert_center - 30, OpenTricks_Table[reel[3]].name, V_20TRANS, "center")
	
	local hint_x = othud.stringWidth(OpenTricks_Table[reel[3]].hint, V_20TRANS, "thin")
	othud.drawString(hori_center - (hint_x/2), vert_center + 20, OpenTricks_Table[reel[3]].hint, V_20TRANS, "thin")
  else
	if (splitscreen < 2)
      othud.draw(icon_x, icon_y, chosenPatches[player.OpenTricks.key], V_HUDTRANS)
	  othud.draw(icon_x, icon_y, cursor_patch, V_HUDTRANS)
    else
      othud.draw(icon_x, icon_y, chosenSmallPatches[player.OpenTricks.key], V_HUDTRANS)
    end
  end
  
  ----------------------
  -- draw trick meter --
  ----------------------
  
  if OpenTricks_TryingTrick(player) --player can trick, is attempting one
    local meter_colors = {20, 25} -- colors
    local edge_colors = {14, 19}
    local meter_num = #meter_colors
    local edge_num = #edge_colors
    local sweet_color = 0
    local sweet_edge_color = 123
    local timer_color = 127
  
    local loop_start = 0 -- meter math
    local loop_end = 64
    local loop_incrementer = 1
    local y_offset = 0
    local x_offset = 16
    local bit_shift = 12
    local max_width = 15
    local actual_timer_max = 32
    local angle_adder = (ANG1 * 3)
    
    local reverse_meter = player.OpenTricks.meter.reversed
    
    local range = OpenTricks_GetRange(player)
    local timer = player.OpenTricks.meter.timer
    local sweetspot = player.OpenTricks.meter.sweetspot
    
    if (splitscreen) 
      meter_y = $/2
      if (splitscreen > 1)
        meter_x = $/2
      end
      loop_end = 32
      bit_shift = 13
      max_width = 7
      if (splitscreen == 1 and cam.pnum == 2)
        y_offset = 50
      elseif (splitscreen > 1 and cam.pnum == 2)
        x_offset = $ + 160
      elseif (splitscreen > 1 and cam.pnum == 3)
        y_offset = 50
      elseif (splitscreen > 1 and cam.pnum == 4)
        x_offset = $ + 160
        y_offset = 50
      end
    else
      angle_adder = $ / 2
    end
    
    local mx = ANGLE_45
    
    for my = loop_start, loop_end, loop_incrementer do
      local mw = min(sin(mx)>>bit_shift, max_width) -- shift the fixed-scale sine by 12 bits, use 15 as the width value if it's smaller
      local smy = (my * actual_timer_max) / abs (loop_start - loop_end) -- use this value to track where we are on a scale of 0 to 32.
      local current_y = (meter_y>>FRACBITS) - my + y_offset
      
      if (reverse_meter)
        current_y = (meter_y>>FRACBITS) - (loop_end - my) + y_offset
      end
      
      if smy == timer
        othud.drawFill((meter_x>>FRACBITS) + mw + x_offset, current_y + y_offset, mw + 1, 1, timer_color)
		othud.draw((meter_x>>FRACBITS) + (mw * 2) + x_offset + 3, current_y + y_offset, meter_cursor)
      elseif (abs(smy - sweetspot) <= range)
        othud.drawFill((meter_x>>FRACBITS) + mw + x_offset, current_y + y_offset, mw, 1, sweet_color)
        othud.drawFill((meter_x>>FRACBITS) + mw + x_offset, current_y + y_offset, 1, 1, sweet_edge_color)
        othud.drawFill((meter_x>>FRACBITS) + mw*2 + x_offset, current_y + y_offset, 1, 1, sweet_edge_color)
      else
        othud.drawFill((meter_x>>FRACBITS) + mw + x_offset, current_y + y_offset, mw, 1, meter_colors[my%meter_num+1])
        othud.drawFill((meter_x>>FRACBITS) + mw + x_offset, current_y + y_offset, 1, 1, edge_colors[my%edge_num+1])
        othud.drawFill((meter_x>>FRACBITS) + mw*2 + x_offset, current_y + y_offset, 1, 1, edge_colors[my%edge_num+1])
      end
      mx = $ + angle_adder
    end
  end
end

hud.add(OpenTricks_Drawer)