#include "holly/background.hpp"
#include "holly/holly.hpp"

#include "scene/emulator/scene.hpp"

#include "holly/ta_bits.hpp"
#include "holly/isp_tsp.hpp"
#include "ta_parameter.hpp"

#include "framebuffer.hpp"
#include "font.hpp"
#include "scene/emulator/sound.hpp"

namespace scene::emulator {
  const struct scene::scene scene = {
    .ta_alloc = ta_alloc_ctrl::pt_opb::_32x4byte
              | ta_alloc_ctrl::tm_opb::no_list
              | ta_alloc_ctrl::t_opb::_32x4byte
              | ta_alloc_ctrl::om_opb::no_list
              | ta_alloc_ctrl::o_opb::no_list,
    .opb_size = {
      .opaque = 0,
      .opaque_modifier = 0,
      .translucent = 32 * 4,
      .translucent_modifier = 0,
      .punch_through = 32 * 4
    },
    .transfer = transfer,
    .interrupt = sound::interrupt,
    .init = init,
    .done = done
  };

  static float intensity = 0.0;

  struct message {
    const char * title;
    const int title_length;
    const char ** paragraph;
    const int paragraph_length;
  };

  const char * counterfeit_title = "Counterfeit Dreamcast Detected";
  const int counterfeit_title_length = 30;
  const char * counterfeit_paragraph[] = {
    "Your counterfeit Dreamcast failed a CORE",
    "rasterization test.",
    "",
    "Dreamcast emulator behavior is highly divergent",
    "from a genuine Sega Dreamcast. Some emulator",
    "authors deliberately choose to forgo accuracy,",
    "and instead are developing a distinct and",
    "unrelated fantasy-platform.",
    "",
    "This program only supports genuine Sega",
    "Dreamcasts. Other fantasy-platforms and emulators",
    "are not supported."
  };
  const int counterfeit_paragraph_length = (sizeof (counterfeit_paragraph)) / (sizeof (counterfeit_paragraph[0]));

  const char * cvbs_title = "CVBS unsupported";
  const int cvbs_title_length = 16;
  const char * cvbs_paragraph[] = {
    "Drawing the UI at",
    "320x240 would require a",
    "complete redesign."
    "",
    "Please switch to VGA."
  };
  const int cvbs_paragraph_length = (sizeof (cvbs_paragraph)) / (sizeof (cvbs_paragraph[0]));

  const char * scart_title = "SCART unsupported";
  const int scart_title_length = 17;

  const message messages[] = {
    [counterfeit] = {
      counterfeit_title,
      counterfeit_title_length,
      counterfeit_paragraph,
      counterfeit_paragraph_length,
    },
    [cvbs] = {
      cvbs_title,
      cvbs_title_length,
      cvbs_paragraph,
      cvbs_paragraph_length,
    },
    [scart] = {
      scart_title,
      scart_title_length,
      cvbs_paragraph,
      cvbs_paragraph_length,
    },
  };

  int current_message_id = 0;

  void draw_title(ta_parameter_writer& writer, int color)
  {
    const font::font& face = font::fonts[font::font::ter_u32n];
    draw_glyph_global(writer, face);

    int length = messages[current_message_id].title_length;
    int h_center = framebuffer.px_width / 2 - (length * face.width) / 2;
    const char * title = messages[current_message_id].title;
    draw_string(writer, face, title, h_center, 35, 0.1, color << 16);
  }

  void draw_paragraph(ta_parameter_writer& writer, int color)
  {

    const font::font& face = font::fonts[font::font::ter_u24n];
    draw_glyph_global(writer, face);

    float x = 26;
    float y = 80;

    int base_color = (color << 16) | (color << 8) | (color << 0);

    int length = messages[current_message_id].paragraph_length;
    const char ** paragraph = messages[current_message_id].paragraph;
    for (int i = 0; i < length; i++) {
      const char * s = paragraph[i];
      draw_string(writer, face, s, x, y, 0.1, base_color);
      y += face.height;
    }
  }

  void transfer(ta_multiwriter& multi)
  {
    using namespace font;

    if (intensity < 1.0)
      intensity += 0.005;

    int color = (int)(255.0 * intensity);
    if (color > 255)
      color = 255;

    draw_title(multi.pt, color);
    draw_paragraph(multi.pt, color);

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

    quad_type_0(multi.op,
                {0, 0, 0.1},
                {0, 0, 0.1},
                {0, 0, 0.1},
                {0, 0, 0.1},
                0x0);
  }

  void init()
  {
    intensity = 0;

    background_parameter2(texture_memory_alloc.background[1].start,
                          0);
    holly.VO_BORDER_COL = 0;

    ::scene::emulator::sound::init();
  }

  int done()
  {
    return -1;
  }
}
