// Copyright 2022 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
// LCD Facade using imgui running on a host machine.
// Much of this code is from the imgui example:
// https://github.com/ocornut/imgui/tree/master/examples/example_glfw_opengl3
// As well as the wiki page:
// https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples

#include "pw_display_driver_imgui/display_driver.h"

#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"

#if defined(IMGUI_IMPL_OPENGL_ES2)
#include <GLES2/gl2.h>
#endif
#include <GLFW/glfw3.h>  // Will pull in system OpenGL headers

#include "pw_framebuffer/reader.h"

using pw::color::color_rgb565_t;
using pw::framebuffer::Framebuffer;
using pw::framebuffer::FramebufferReader;
using pw::framebuffer::PixelFormat;

namespace pw::display_driver {

namespace {

constexpr uint16_t kDisplayWidth = 320;
constexpr uint16_t kDisplayHeight = 240;
constexpr size_t kDisplayDataSize = kDisplayWidth * kDisplayHeight;

// OpenGL texture data.
GLuint lcd_pixel_data[kDisplayDataSize];

// imgui state
bool show_imgui_demo_window = false;
ImVec4 clear_color = ImVec4(0.27f, 0.27f, 0.27f, 1.00f);
GLuint lcd_texture = 0;
GLFWwindow* window;
int lcd_texture_display_scale = 3;
int old_lcd_texture_display_scale = 0;
bool lcd_texture_display_mode_nearest = true;
bool old_lcd_texture_display_mode_nearest = true;

ImGuiMousePosition touchscreen_mouse_position;

void CleanupAndExit() {
  ImGui_ImplOpenGL3_Shutdown();
  ImGui_ImplGlfw_Shutdown();
  ImGui::DestroyContext();

  glfwDestroyWindow(window);
  glfwTerminate();
  exit(0);
}

void HelpMarker(const char* desc) {
  ImGui::TextDisabled("(?)");
  if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort)) {
    ImGui::BeginTooltip();
    ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
    ImGui::TextUnformatted(desc);
    ImGui::PopTextWrapPos();
    ImGui::EndTooltip();
  }
}

void _SetTexturePixel(
    GLuint x, GLuint y, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
  // Calculate target color
  GLuint target_color;
  GLubyte* colors = (GLubyte*)&target_color;
  colors[0] = r;
  colors[1] = g;
  colors[2] = b;
  colors[3] = a;
  lcd_pixel_data[y * kDisplayWidth + x] = target_color;
}

void _SetTexturePixel(GLuint x, GLuint y, uint8_t r, uint8_t g, uint8_t b) {
  _SetTexturePixel(x, y, r, g, b, 255);
}

void _SetTexturePixel(GLuint x, GLuint y, color_rgb565_t rgb565) {
  pw::color::ColorRGBA c(rgb565);
  _SetTexturePixel(x, y, c.r, c.g, c.b, 255);
}

void UpdateLcdTexture() {
  // Set current texture
  glBindTexture(GL_TEXTURE_2D, lcd_texture);
  // Update texture
  glTexSubImage2D(GL_TEXTURE_2D,
                  0,
                  0,
                  0,
                  kDisplayWidth,
                  kDisplayHeight,
                  GL_RGBA,
                  GL_UNSIGNED_BYTE,
                  lcd_pixel_data);
  // Unbind texture
  glBindTexture(GL_TEXTURE_2D, 0);
}

void SetupLcdTexture(GLuint* out_texture) {
  // Create a OpenGL texture identifier
  GLuint image_texture;
  glGenTextures(1, &image_texture);
  glBindTexture(GL_TEXTURE_2D, image_texture);

  // Setup filtering parameters for display
  GLuint display_mode =
      lcd_texture_display_mode_nearest ? GL_NEAREST : GL_LINEAR;
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, display_mode);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, display_mode);
  glTexParameteri(GL_TEXTURE_2D,
                  GL_TEXTURE_WRAP_S,
                  GL_CLAMP_TO_EDGE);  // This is required on WebGL for non
                                      // power-of-two textures
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);  // Same

  // Upload pixels into texture
#if defined(GL_UNPACK_ROW_LENGTH) && !defined(__EMSCRIPTEN__)
  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
#endif
  glTexImage2D(GL_TEXTURE_2D,
               0,
               GL_RGBA,
               kDisplayWidth,
               kDisplayHeight,
               0,
               GL_RGBA,
               GL_UNSIGNED_BYTE,
               lcd_pixel_data);

  glBindTexture(GL_TEXTURE_2D, 0);

  *out_texture = image_texture;
}

void glfw_error_callback(int error, const char* description) {
  fprintf(stderr, "Glfw Error %d: %s\n", error, description);
}

}  // namespace

DisplayDriverImgUI::DisplayDriverImgUI() = default;

Status DisplayDriverImgUI::Init() {
  // Setup window
  glfwSetErrorCallback(glfw_error_callback);
  if (!glfwInit()) {
    return Status::Internal();
  }

  // Decide GL+GLSL versions
#if defined(IMGUI_IMPL_OPENGL_ES2)
  // GL ES 2.0 + GLSL 100
  const char* glsl_version = "#version 100";
  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
  glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
#elif defined(__APPLE__)
  // GL 3.2 + GLSL 150
  const char* glsl_version = "#version 150";
  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
  glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);  // 3.2+ only
  glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);  // Required on Mac
#else
  // GL 3.0 + GLSL 130
  const char* glsl_version = "#version 130";
  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
  // glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);  // 3.2+
  // only glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // 3.0+ only
#endif

  // Create window with graphics context
  window = glfwCreateWindow(1280, 800, "pw_display", nullptr, nullptr);
  if (window == nullptr)
    return Status::Internal();
  glfwMakeContextCurrent(window);
  glfwSwapInterval(1);  // Enable vsync

  // Setup Dear ImGui context
  IMGUI_CHECKVERSION();
  ImGui::CreateContext();
  ImGuiIO& io = ImGui::GetIO();
  (void)io;
  // io.Fonts->AddFontFromFileTTF("NotoSans-Regular.ttf", 32.0);

  // Enable Keyboard Controls
  io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
  io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
  io.ConfigFlags |= ImGuiConfigFlags_DpiEnableScaleFonts;
  // Enable Gamepad Controls
  // io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;

  // Setup Dear ImGui style
  ImGui::StyleColorsDark();
  // ImGui::StyleColorsLight();
  // ImGui::StyleColorsClassic();

  // Setup Platform/Renderer backends
  ImGui_ImplGlfw_InitForOpenGL(window, true);
  ImGui_ImplOpenGL3_Init(glsl_version);

  SetupLcdTexture(&lcd_texture);
  return OkStatus();
}

void DisplayDriverImgUI::RecreateLcdTexture() {
  if (old_lcd_texture_display_mode_nearest !=
      lcd_texture_display_mode_nearest) {
    old_lcd_texture_display_mode_nearest = lcd_texture_display_mode_nearest;
    SetupLcdTexture(&lcd_texture);
  }
}

void DisplayDriverImgUI::Render() {
  UpdateLcdTexture();

  // Poll and handle events (inputs, window resize, etc.)
  glfwPollEvents();

  touchscreen_mouse_position.left_button_pressed = false;
  double mouse_xpos = 0, mouse_ypos = 0;
  glfwGetCursorPos(window, &mouse_xpos, &mouse_ypos);
  if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS) {
    touchscreen_mouse_position.left_button_pressed = true;
  }

  // Start the Dear ImGui frame
  ImGui_ImplOpenGL3_NewFrame();
  ImGui_ImplGlfw_NewFrame();
  ImGui::NewFrame();
  ImGuiIO& io = ImGui::GetIO();

  int display_w, display_h;
  glfwGetFramebufferSize(window, &display_w, &display_h);

  // Build the empty dockspace background

  static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None;
  ImGuiWindowFlags window_flags =
      ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
  const ImGuiViewport* viewport = ImGui::GetMainViewport();
  ImGui::SetNextWindowPos(viewport->WorkPos);
  ImGui::SetNextWindowSize(viewport->WorkSize);
  ImGui::SetNextWindowViewport(viewport->ID);
  ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
  ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
  window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse |
                  ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
  window_flags |=
      ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;

  // 0px padding around the dockspace
  ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
  // Start docspace window
  ImGui::Begin("DockSpace", NULL, window_flags);

  // Create empty dockspace container
  ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
  ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);

  ImGui::PopStyleVar();   // Padding around docspace window
  ImGui::PopStyleVar(2);  // WindowRounding and WindowBorderSize

  // Dockspace menu
  if (ImGui::BeginMenuBar()) {
    if (ImGui::BeginMenu("Options")) {
      ImGui::MenuItem("Show Imgui Demo Window", "", &show_imgui_demo_window);
      ImGui::Separator();
      if (ImGui::MenuItem("Quit")) {
        CleanupAndExit();
      }
      ImGui::EndMenu();
    }
    HelpMarker(
        "Window Docking: "
        "\n"
        "- Drag from window title bar or their tab to dock/undock."
        "\n"
        "- Drag from window menu button (upper-left button) to undock an "
        "entire node (all windows)."
        "\n"
        "- Hold SHIFT to disable docking");

    ImGui::EndMenuBar();
  }

  ImGui::End();  // end dockspace

  // 1. Show the big demo window (Most of the sample code is in
  // ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear
  // ImGui!).
  if (show_imgui_demo_window) {
    ImGui::ShowDemoWindow(&show_imgui_demo_window);
  }

  // Draw Screen(s)

  // Screen 1 Window
  ImGui::Begin("Screen 1");
  // Calculate the display texture draw coordinates
  int scaled_width = kDisplayWidth * lcd_texture_display_scale;
  int scaled_height = kDisplayHeight * lcd_texture_display_scale;

  ImVec2 mouse_pos = ImGui::GetCursorScreenPos();
  ImVec2 mouse_coordinates_of_base_image;
  ImGui::Image((void*)(intptr_t)lcd_texture,
               ImVec2(scaled_width, scaled_height),
               // Top left texure coord
               ImVec2(0.0f, 0.0f),
               // Lower right texture coord
               ImVec2(1.0f, 1.0f),
               // Tint (none applied)
               ImVec4(1.0f, 1.0f, 1.0f, 1.0f),
               // Border color (50% white)
               ImVec4(1.0f, 1.0f, 1.0f, 0.5f));
  mouse_coordinates_of_base_image.x =
      floor((io.MousePos.x - mouse_pos.x) / lcd_texture_display_scale);
  mouse_coordinates_of_base_image.y =
      floor((io.MousePos.y - mouse_pos.y) / lcd_texture_display_scale);
  if (ImGui::IsItemHovered()) {
    ImGui::BeginTooltip();
    ImGui::Text("mouse coords = %.1f, %.1f",
                mouse_coordinates_of_base_image.x,
                mouse_coordinates_of_base_image.y);
    ImGui::EndTooltip();
  }
  ImGui::End();  // Screen 1 Window

  // For reference this forces the "Screen 1" window to be docked to the main
  // dockspace:
  //   ImGui::DockBuilderDockWindow("Screen 1", dockspace_id);

  ImGui::Begin("Screen 1 Settings");
  ImGui::Text("Pixel Size = %d x %d", kDisplayWidth, kDisplayHeight);
  ImGui::SliderInt("Integer Scaling", &lcd_texture_display_scale, 1, 10);
  ImGui::Checkbox("Nearest neighbor", &lcd_texture_display_mode_nearest);

  ImGui::Separator();
  touchscreen_mouse_position.position_x = mouse_coordinates_of_base_image.x;
  touchscreen_mouse_position.position_y = mouse_coordinates_of_base_image.y;
  ImGui::Text("Mouse position = %d, %d",
              touchscreen_mouse_position.position_x,
              touchscreen_mouse_position.position_y);
  ImGui::Text("Mouse Left button pressed: %d",
              touchscreen_mouse_position.left_button_pressed);

  // Demo Window toggle
  ImGui::Separator();

  ImGui::Text("Application average %.3f ms/frame (%.1f FPS)",
              1000.0f / ImGui::GetIO().Framerate,
              ImGui::GetIO().Framerate);

  ImGui::End();

  // Done building the UI
  ImGui::Render();

  glViewport(0, 0, display_w, display_h);
  glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
  glClear(GL_COLOR_BUFFER_BIT);
  // Render ImGui
  ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

  glfwSwapBuffers(window);

  if (glfwWindowShouldClose(window)) {
    CleanupAndExit();
  }
}

void DisplayDriverImgUI::WriteFramebuffer(Framebuffer framebuffer,
                                          WriteCallback write_callback) {
  PW_ASSERT(framebuffer.is_valid());
  PW_ASSERT(framebuffer.pixel_format() == PixelFormat::RGB565);
  RecreateLcdTexture();

  FramebufferReader reader(framebuffer);
  // Copy frame_buffer into lcd_pixel_data
  for (GLuint x = 0; x < kDisplayWidth; x++) {
    for (GLuint y = 0; y < kDisplayHeight; y++) {
      if (auto c = reader.GetPixel(x, y); c.ok()) {
        _SetTexturePixel(x, y, c.value());
      }
    }
  }

  Render();
  write_callback(std::move(framebuffer), OkStatus());
}

Status DisplayDriverImgUI::WriteRow(span<uint16_t> row_pixels,
                                    uint16_t row_idx,
                                    uint16_t col_idx) {
  RecreateLcdTexture();

  for (auto c : row_pixels) {
    _SetTexturePixel(col_idx++, row_idx, c);
  }

  // Rendering here is horribly slow - come up with better solution.
  Render();
  return OkStatus();
}

uint16_t DisplayDriverImgUI::GetWidth() const { return kDisplayWidth; }

uint16_t DisplayDriverImgUI::GetHeight() const { return kDisplayHeight; }

GLFWwindow* DisplayDriverImgUI::GetGlfwWindow() { return window; }

ImGuiMousePosition DisplayDriverImgUI::GetImGuiMousePosition() {
  return touchscreen_mouse_position;
}

}  // namespace pw::display_driver
