#include "graphics_primitive.hpp"
#include "tracklist.hpp"
#include "ta_parameter.hpp"
#include "playlist.hpp"
#include "interpreter.hpp"

#include "widget/button_label.hpp"
#include "widget/left_aligned.hpp"

namespace scene::tracker::tracklist {

  static bool samples_tab = false;

  void playlist_click()
  {
    samples_tab = false;
  }

  void samples_click()
  {
    samples_tab = true;
  }

  const float width = glyph::hori_advance * 20 + 3 * 2;
  const int line_rows_half = 5;
  const int line_rows = line_rows_half * 2 + 1;
  const float height = glyph::vert_advance * line_rows + 3 * 2;

#define __length(c) ((sizeof (c)) / (sizeof (c[0])))

  widget::button_label playlist_button(width / 2 - 1, 20, "playlist", playlist_click);
  widget::button_label instruments_button(width / 2 - 1, 20, "samples", samples_click);

  widget::widget * playlist_instruments_children[] = {
    &playlist_button,
    &instruments_button,
  };
  int playlist_instruments_length = __length(playlist_instruments_children);

  widget::left_aligned playlist_instruments(0, 0, 1, playlist_instruments_children, playlist_instruments_length);

  void draw_borders(ta_parameter_writer& writer, float x, float y)
  {
    transfer_horizontal_border(writer, x, y, width);
    transfer_horizontal_border(writer, x, y + height - 3, width);

    transfer_vertical_border(writer, x, y, height);
    transfer_vertical_border(writer, x + width - 3, y, height);
  }

  void draw_track_names(ta_parameter_writer& writer, float x, float y)
  {
    for (int i = 0; i < line_rows; i++) {
      int track_ix = playlist::state.playlist_ix - line_rows_half + i;

      if (track_ix >= 0 && track_ix < playlist::playlist_length) {
        const char * title = playlist::playlist[track_ix].title;
        transfer_string(writer, title,
                        x, y, 1.0 / 10.0,
                        0xffffff);
      }
      y += glyph::vert_advance;
    }
  }

  void draw_sample_names(ta_parameter_writer& writer, float x, float y)
  {
    int count = interpreter::state.xm.header->number_of_instruments;
    for (int i = 0; i < count; i++) {
      if (i >= line_rows)
        break;

      transfer_string(writer, (const char *)interpreter::state.xm.instrument_header[i]->instrument_name,
                      x, y, 1.0 / 10.0,
                      0xffffff);
      y += glyph::vert_advance;
    }
  }

  void draw_middle_line(ta_parameter_writer& writer, float x, float y)
  {
    int middle_width = width;
    int middle_height = glyph::vert_advance - 1;

    y += 2;

    y += glyph::vert_advance * (line_rows_half + 1);

    quad_type_0(writer,
                {x + 0, y + 0, 1.0 / 20.0},
                {x + 0, y + 1, 1.0 / 20.0},
                {x + middle_width, y + 1, 1.0 / 20.0},
                {x + middle_width, y + 0, 1.0 / 20.0},
                0x555555);

    y += 1;

    quad_type_0(writer,
                {x + 0, y + 0, 1.0 / 20.0},
                {x + 0, y + middle_height, 1.0 / 20.0},
                {x + middle_width, y + middle_height, 1.0 / 20.0},
                {x + middle_width, y + 0, 1.0 / 20.0},
                0x404040);

    y += middle_height;

    quad_type_0(writer,
                {x + 0, y + 0, 1.0 / 20.0},
                {x + 0, y + 1, 1.0 / 20.0},
                {x + middle_width, y + 1, 1.0 / 20.0},
                {x + middle_width, y + 0, 1.0 / 20.0},
                0x202020);
  }

  void draw_heading(ta_parameter_writer& writer, float x, float y)
  {
    transfer_string(writer, "playlist:",
                    x, y, 1.0 / 10.0,
                    0xa7a7a7);

    transfer_string(writer, "(    /    )",
                    x + glyph::hori_advance * 10, y, 1.0 / 11.0,
                    0xa7a7a7);

    transfer_integer(writer, playlist::state.playlist_ix + 1,
                     x + glyph::hori_advance * (10 + 2), y, 1.0 / 10.0,
                     2, ' ',
                     0xffffff);

    transfer_integer(writer, playlist::playlist_length,
                     x + glyph::hori_advance * (10 + 7), y, 1.0 / 10.0,
                     2, ' ',
                     0xffffff);
  }

  void draw_tab_connector(ta_parameter_writer& writer, float x, float y)
  {
    const static float background_depth = 1.0 / 9.5;
    const static int background_color = 0x282c2c;

    const static float shadow_depth = 1.0 / 10.0;
    const static int shadow_color = 0x0000000;

    float x0;

    if (samples_tab) {
      x0 = x + width / 2 + 2;
    } else {
      x0 = x + 2;
    }

    float y0 = y;
    float x1 = x0 + width / 2 - 5;
    float y1 = y0 + 5;

    quad_type_0(writer,
                {x0, y0, background_depth},
                {x1, y0, background_depth},
                {x1, y1, background_depth},
                {x0, y1, background_depth},
                background_color);

    quad_type_0(writer,
                {x0 - 1, y0, shadow_depth},
                {x1 + 1, y0, shadow_depth},
                {x1 + 1, y1, shadow_depth},
                {x0 - 1, y1, shadow_depth},
                shadow_color);
  }

  void init(float x, float y)
  {
    playlist_instruments.freeze(x, y);
  }

  void update_pick(cursor::cursor& c)
  {
    widget::widget * w = playlist_instruments.pick(c.x, c.y);
    if (w != nullptr) {
      w->click();
    }
  }

  void draw(ta_multiwriter& multi, float x, float y)
  {
    transfer_global_polygon_glyph(multi.pt);

    playlist_instruments.draw(multi);
    //draw_heading(multi.pt, x, y);

    y = y + playlist_instruments.height - 10;

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

    draw_tab_connector(multi.op, x, y + 10 - 2);


    float yi = y + glyph::vert_advance + 3;
    draw_borders(multi.op, x, yi);

    if (samples_tab) {
      draw_sample_names(multi.pt, x + 3, yi + 3);
    } else {
      draw_track_names(multi.pt, x + 3, yi + 3);
      draw_middle_line(multi.op, x, y + 3);
    }
  }
}
