// Copyright 2024 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.

#include "pw_draw/draw.h"

#include <math.h>

#include "pw_color/color.h"
#include "pw_draw/font_set.h"
#include "pw_draw/sprite_sheet.h"
#include "pw_framebuffer/framebuffer.h"
#include "pw_framebuffer/writer.h"

using pw::color::color_rgb565_t;
using pw::framebuffer::Framebuffer;
using pw::framebuffer::FramebufferWriter;
using pw::geometry::Size;
using pw::geometry::Vector2;

namespace pw::draw {

void DrawLine(
    Framebuffer& fb, int x1, int y1, int x2, int y2, color_rgb565_t pen_color) {
  // Bresenham's Line Algorithm
  int16_t steep_gradient = abs(y2 - y1) > abs(x2 - x1);
  // Swap values
  int16_t temp;
  if (steep_gradient) {
    temp = x1;
    x1 = y1;
    y1 = temp;
    temp = x2;
    x2 = y2;
    y2 = temp;
  }
  if (x1 > x2) {
    temp = x1;
    x1 = x2;
    x2 = temp;
    temp = y1;
    y1 = y2;
    y2 = temp;
  }

  int16_t dx = x2 - x1;
  int16_t dy = abs(y2 - y1);
  int16_t error_value = dx / 2;
  int16_t ystep = y1 < y2 ? 1 : -1;

  FramebufferWriter writer(fb);
  for (; x1 <= x2; x1++) {
    if (steep_gradient) {
      writer.SetPixel(y1, x1, pen_color);
    } else {
      writer.SetPixel(x1, y1, pen_color);
    }
    error_value -= dy;
    if (error_value < 0) {
      y1 += ystep;
      error_value += dx;
    }
  }
}

// Draw a circle at center_x, center_y with given radius and color. Only a
// one-pixel outline is drawn if filled is false.
void DrawCircle(Framebuffer& fb,
                int center_x,
                int center_y,
                int radius,
                color_rgb565_t pen_color,
                bool filled = false) {
  int fx = 0, fy = 0;
  int x = -radius, y = 0;
  int error_value = 2 - 2 * radius;
  FramebufferWriter writer(fb);
  while (x < 0) {
    if (!filled) {
      fx = x;
      fy = y;
    }
    // Draw each quarter circle
    for (int i = x; i <= fx; i++) {
      // Lower right
      writer.SetPixel(center_x - i, center_y + y, pen_color);
      // Upper left
      writer.SetPixel(center_x + i, center_y - y, pen_color);
    }
    for (int i = fy; i <= y; i++) {
      // Lower left
      writer.SetPixel(center_x - i, center_y - x, pen_color);
      // Upper right
      writer.SetPixel(center_x + i, center_y + x, pen_color);
    }
    radius = error_value;
    if (radius <= y) {
      y++;
      error_value += y * 2 + 1;
    }
    if (radius > x || error_value > y) {
      x++;
      error_value += x * 2 + 1;
    }
  }
}

void DrawHLine(
    Framebuffer& fb, int x1, int x2, int y, color_rgb565_t pen_color) {
  FramebufferWriter writer(fb);
  for (int i = x1; i <= x2; i++) {
    writer.SetPixel(i, y, pen_color);
  }
}

void DrawRect(Framebuffer& fb,
              int x1,
              int y1,
              int x2,
              int y2,
              color_rgb565_t pen_color,
              bool filled = false) {
  // Draw top and bottom lines.
  DrawHLine(fb, x1, x2, y1, pen_color);
  DrawHLine(fb, x1, x2, y2, pen_color);
  if (filled) {
    for (int y = y1 + 1; y < y2; y++) {
      DrawHLine(fb, x1, x2, y, pen_color);
    }
  } else {
    FramebufferWriter writer(fb);
    for (int y = y1 + 1; y < y2; y++) {
      writer.SetPixel(x1, y, pen_color);
      writer.SetPixel(x2, y, pen_color);
    }
  }
}

void DrawRectWH(Framebuffer& fb,
                int x,
                int y,
                int w,
                int h,
                color_rgb565_t pen_color,
                bool filled = false) {
  DrawRect(fb, x, y, x - 1 + w, y - 1 + h, pen_color, filled);
}

void Fill(Framebuffer& fb, color_rgb565_t pen_color) {
  FramebufferWriter writer(fb);
  writer.Fill(pen_color);
}

void DrawSprite(Framebuffer& fb,
                int x,
                int y,
                pw::draw::SpriteSheet* sprite_sheet,
                int integer_scale = 1) {
  uint16_t color;
  int start_x, start_y;
  FramebufferWriter writer(fb);
  for (int current_x = 0; current_x < sprite_sheet->width; current_x++) {
    for (int current_y = 0; current_y < sprite_sheet->height; current_y++) {
      color = sprite_sheet->GetColor(
          current_x, current_y, sprite_sheet->current_index);
      if (color != sprite_sheet->transparent_color) {
        if (integer_scale == 1) {
          writer.SetPixel(x + current_x, y + current_y, color);
        }
        // If integer_scale > 1: draw a rectangle
        else if (integer_scale > 1) {
          start_x = x + (integer_scale * current_x);
          start_y = y + (integer_scale * current_y);
          DrawRectWH(
              fb, start_x, start_y, integer_scale, integer_scale, color, true);
        }
      }
    }
  }
}

void DrawTestPattern(Framebuffer& fb) {
  color_rgb565_t color = pw::color::ColorRgba(0x00, 0xFF, 0xFF).ToRgb565();
  // Create a Test Pattern
  FramebufferWriter writer(fb);
  for (int x = 0; x < fb.size().width; x++) {
    for (int y = 0; y < fb.size().height; y++) {
      if (y % 10 != x % 10) {
        writer.SetPixel(x, y, color);
      }
    }
  }
}

Size<int> DrawCharacter(int ch,
                        Vector2<int> pos,
                        color_rgb565_t fg_color,
                        color_rgb565_t bg_color,
                        const FontSet& font,
                        Framebuffer& framebuffer) {
  if (ch < font.starting_character || ch > font.ending_character) {
    return Size<int>{0, font.height};
  }
  const int character_index = (int)ch - font.starting_character;

  FramebufferWriter writer(framebuffer);
  for (int font_row = 0; font_row < font.height; font_row++) {
    for (int font_column = 0; font_column < font.width; font_column++) {
      const bool pixel_on =
          PW_FONT_BIT(font.width - font_column - 1,
                      font.data[font.height * character_index + font_row]);
      writer.SetPixel(pos.x + font_column,
                      pos.y + font_row,
                      pixel_on ? fg_color : bg_color);
    }
  }
  return Size<int>{font.width, font.height};
}

Size<int> DrawString(std::wstring_view str,
                     Vector2<int> pos,
                     color_rgb565_t fg_color,
                     color_rgb565_t bg_color,
                     const FontSet& font,
                     Framebuffer& framebuffer) {
  Size<int> string_dimensions{0, font.height};
  for (const wchar_t& ch : str) {
    auto char_dimensions =
        DrawCharacter(ch, pos, fg_color, bg_color, font, framebuffer);
    pos.x += char_dimensions.width;
    string_dimensions.width += char_dimensions.width;
  }
  return string_dimensions;
}

}  // namespace pw::draw
