local prefix = "otrx"
local otrx_range = CV_FindVar(prefix .. "_range")
local otrx_spb_range = CV_FindVar(prefix .. "_spb_range")
local OR_GetSplitscreenCoords = OR_GetSplitscreenCoords
local OR_GetOTricksIconCoords = OR_GetOTricksIconCoords

local function OpenTricks_GetValidStyles(input)
  local filtered = {}
  for key, value in pairs(input)
    if not value.banned
      filtered[key] = value
    end
  end
  return filtered
end

local function OpenTricks_GetFivePatches(index)
  local indices = {}
  local x = index - 1
  
  while (#indices < 5 or x != index) do -- Loop through table until we have five indices and we've reached the selected index.
	x = $ + 1
  
    while OpenTricks_Table[x] and (OpenTricks_Table[x].banned == true)
      x = $ + 1
    end
    
    while x > #OpenTricks_Table do
      x = $ % #OpenTricks_Table
    end
    
    while x < 1 do
      x = #OpenTricks_Table + i
    end
	
	table.insert(indices, x)
  end
  
  local j = #indices
  local valid = OpenTricks_GetValidStyles(OpenTricks_Table_Pending)
  if #valid == 0 
    return {indices[1], indices[1], indices[1], indices[1], indices[1]}
  else
    return {indices[j-2], indices[j-1], indices[1], indices[2], indices[3]}
  end
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 + 51 + (leveltime / 5 % 2), vert_center, right_patch)
    
	local valid = OpenTricks_GetValidStyles(OpenTricks_Table_Pending)
	if #valid == 0
	  othud.drawString(hori_center, vert_center - 30, "Oops! All " + OpenTricks_Table[reel[3]].name, V_20TRANS, "center")
	else
      othud.drawString(hori_center, vert_center - 30, OpenTricks_Table[reel[3]].name, V_20TRANS, "center")
	end
    
    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, true)
    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)