#include "../../ta_parameter.hpp"
#include "../../graphics_primitive.hpp"
#include "../../interpreter.hpp"
#include "../../framebuffer.hpp"

#include "channel_status.hpp"
#include "texture.hpp"

static inline int round_up_div(int n, int m)
{
  int div = n / m;
  int rem = n % m;
  if (rem == 0)
    return div;
  return div + 1;
}

static inline int round_up(int n, int m)
{
  int rem = n % m;
  if (rem == 0)
    return n;
  return n + m - rem;
}

namespace scene::tracker::channel_status {

void draw(ta_multiwriter& multi, int x, int y)
{
  using namespace interpreter;

  int px_width = framebuffer.px_width - (10 - 3);

  int max_channels_per_row = px_width / 40;
  int rows = round_up_div(state.xm.number_of_channels, max_channels_per_row);
  assert(rows > 0);
  int number_of_channels = round_up(state.xm.number_of_channels, rows);
  int channels_per_row = number_of_channels / rows;
  int width_per_col = (px_width - 3) / channels_per_row;
  int offset = (px_width - (width_per_col * channels_per_row)) / 2;

  int inner_width = width_per_col - 3;

  int height_per_row = height / rows;
  int vert_center = height_per_row / 2 - glyph::vert_advance / 2;

  int ch = 0;
  for (int row = 0; row < rows; row++) {
    int xi = x + offset - 2;

    global_polygon_untextured(multi.op,
                              para_control::list_type::opaque,
                              tsp_instruction_word::dst_alpha_instr::zero);

    transfer_horizontal_border(multi.op, xi, y, width_per_col * channels_per_row);

    for (int col = 0; col < channels_per_row; col++) {

      global_polygon_untextured(multi.op,
                                para_control::list_type::opaque,
                                tsp_instruction_word::dst_alpha_instr::zero);

      transfer_vertical_border(multi.op, xi, y, height_per_row);

      int keyon = 128 * (state.channel[ch].keyon - 224) / 16;
      if (keyon < 0) keyon = 0;
      uint32_t base_color = (keyon << 16) | (keyon << 8) | (keyon << 0);
      transfer_rectangle(multi.op,
                         xi, y, 1.0 / 10000.0,
                         width_per_col, height_per_row,
                         base_color);

      if (ch < state.xm.number_of_channels) {
        transfer_global_polygon_glyph(multi.pt);

        int hori_center = inner_width / 2 - (glyph::hori_advance * ((ch + 1) >= 10)) / 2;
        transfer_integer(multi.pt, ch + 1,
                         xi + hori_center, y + vert_center, 0.1f,
                         0, 0,
                         0xa7a7a7);
      }

      xi += width_per_col;
      ch += 1;
    }

    global_polygon_untextured(multi.op,
                              para_control::list_type::opaque,
                              tsp_instruction_word::dst_alpha_instr::zero);

    transfer_vertical_border(multi.op, xi, y, height_per_row);

    y += height_per_row;
  }

  int xi = x + offset - 2;
  transfer_horizontal_border(multi.op, xi, y, width_per_col * channels_per_row);

  //borders(multi, x, y);
}

}
