/*
 * Copyright 2019 University of Toronto
 *
 * 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
 *
 *      http://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.
 *
 * Authors: Mario Badr, Sameh Attia and Tanner Young-Schultz
 */

#include "ezgl/graphics.hpp"

#include <cassert>
#include <glib.h>

namespace ezgl {

renderer::renderer(cairo_t *cairo,
    transform_fn transform,
    camera *p_camera,
    cairo_surface_t *m_surface)
    : m_cairo(cairo), m_transform(std::move(transform)), m_camera(p_camera), rotation_angle(0)
{
#ifdef EZGL_USE_X11
  // Check if the created cairo surface is an XLIB surface
  if (cairo_surface_get_type(m_surface) == CAIRO_SURFACE_TYPE_XLIB) {
    // get the underlying x11 drawable used by cairo surface
    x11_drawable = cairo_xlib_surface_get_drawable(m_surface);

    // get the x11 display
    x11_display = cairo_xlib_surface_get_display(m_surface);

    // create the x11 context from the drawable of the cairo surface
    if (x11_display != nullptr) {
      x11_context = XCreateGC(x11_display, x11_drawable, 0, 0);
    }
  }
#endif
}

renderer::~renderer()
{
#ifdef EZGL_USE_X11
  // free the x11 context
  if (x11_display != nullptr) {
    XFreeGC(x11_display, x11_context);
  }
#endif
}

void renderer::set_coordinate_system(t_coordinate_system new_coordinate_system)
{
  current_coordinate_system = new_coordinate_system;
}

void renderer::set_visible_world(rectangle new_world)
{
  // Change the aspect ratio of the new_world to align with the aspect ratio of the initial world
  // Get the width and height of the new_world
  point2d n_center = new_world.center();
  double n_width = new_world.width();
  double n_height = new_world.height();

  // Get the aspect ratio of the initial world
  double i_width = m_camera->get_initial_world().width();
  double i_height = m_camera->get_initial_world().height();
  double i_aspect_ratio = i_width / i_height;

  // Make sure the required area is entirely visible
  if (n_width/i_aspect_ratio >= n_height) {
    // Change the height
    double new_height = n_width/i_aspect_ratio;
    new_world ={{n_center.x-n_width/2, n_center.y-new_height/2}, n_width, new_height};
  }
  else {
    // Change the width
    double new_width = n_height/i_aspect_ratio;
    new_world ={{n_center.x-new_width/2, n_center.y-n_height/2}, new_width, n_height};
  }

  // set the visible bounds of the world
  m_camera->set_world(new_world);
}

rectangle renderer::get_visible_world()
{
  // m_camera->get_world() is not good representative of the visible world since it doesn't
  // account for the drawable margins.
  // TODO: precalculate the visible world in camera class to speedup the clipping

  // Get the world and screen dimensions
  rectangle world = m_camera->get_world();
  rectangle screen = m_camera->get_screen();

  // Calculate the margins by converting the screen origin to world coordinates
  point2d margin = screen.bottom_left() * m_camera->get_world_scale_factor();

  // The actual visible world
  return {(world.bottom_left() - margin), (world.top_right() + margin)};
}

rectangle renderer::get_visible_screen()
{
  // Get the widget dimensions
  return m_camera->get_widget();
}

rectangle renderer::world_to_screen(const rectangle& box)
{
  point2d origin = m_transform(box.bottom_left());
  point2d top_right = m_transform(box.top_right());

  return rectangle(origin, top_right);
}

bool renderer::rectangle_off_screen(rectangle rect)
{
  if(current_coordinate_system == SCREEN)
    return false;

  rectangle visible = get_visible_world();

  if(rect.right() < visible.left())
    return true;

  if(rect.left() > visible.right())
    return true;

  if(rect.top() < visible.bottom())
    return true;

  if(rect.bottom() > visible.top())
    return true;

  return false;
}

void renderer::set_color(color c)
{
  set_color(c.red, c.green, c.blue, c.alpha);
}

void renderer::set_color(color c, uint_fast8_t alpha)
{
  set_color(c.red, c.green, c.blue, alpha);
}

void renderer::set_color(uint_fast8_t red,
    uint_fast8_t green,
    uint_fast8_t blue,
    uint_fast8_t alpha)
{
  // set color for cairo
  cairo_set_source_rgba(m_cairo, red / 255.0, green / 255.0, blue / 255.0, alpha / 255.0);

#ifdef EZGL_USE_X11
  // check transparency
  if(alpha != 255)
    transparency_flag = true;
  else
    transparency_flag = false;

  // set color for x11 (no transparency)
  if (x11_display != nullptr) {
    unsigned long xcolor = 0;
    xcolor |= (red << 2 * 8 | red << 8 | red) & 0xFF0000;
    xcolor |= (green << 2 * 8 | green << 8 | green) & 0xFF00;
    xcolor |= (blue << 2 * 8 | blue << 8 | blue) & 0xFF;
    xcolor |= 0xFF000000;
    XSetForeground(x11_display, x11_context, xcolor);
  }
#endif
}

void renderer::set_line_cap(line_cap cap)
{
  auto cairo_cap = static_cast<cairo_line_cap_t>(cap);
  cairo_set_line_cap(m_cairo, cairo_cap);

#ifdef EZGL_USE_X11
  if (x11_display != nullptr) {
    current_line_cap = cap;
    XSetLineAttributes(x11_display, x11_context, current_line_width,
        current_line_dash == line_dash::none ? LineSolid : LineOnOffDash,
        current_line_cap == line_cap::butt ? CapButt : CapRound, JoinMiter);
  }
#endif
}

void renderer::set_line_dash(line_dash dash)
{
  if(dash == line_dash::none) {
    int num_dashes = 0; // disables dashing

    cairo_set_dash(m_cairo, nullptr, num_dashes, 0);
  } else if(dash == line_dash::asymmetric_5_3) {
    static double dashes[] = {5.0, 3.0};
    int num_dashes = 2; // asymmetric dashing

    cairo_set_dash(m_cairo, dashes, num_dashes, 0);
  }

#ifdef EZGL_USE_X11
  if (x11_display != nullptr) {
    current_line_dash = dash;
    XSetLineAttributes(x11_display, x11_context, current_line_width,
        current_line_dash == line_dash::none ? LineSolid : LineOnOffDash,
        current_line_cap == line_cap::butt ? CapButt : CapRound, JoinMiter);
  }
#endif
}

void renderer::set_line_width(int width)
{
  cairo_set_line_width(m_cairo, width == 0 ? 1 : width);

#ifdef EZGL_USE_X11
  if (x11_display != nullptr) {
    current_line_width = width;
    XSetLineAttributes(x11_display, x11_context, current_line_width,
        current_line_dash == line_dash::none ? LineSolid : LineOnOffDash,
        current_line_cap == line_cap::butt ? CapButt : CapRound, JoinMiter);
  }
#endif
}

void renderer::set_font_size(double new_size)
{
  cairo_set_font_size(m_cairo, new_size);
}

void renderer::format_font(std::string const &family, font_slant slant, font_weight weight)
{
  cairo_select_font_face(m_cairo, family.c_str(), static_cast<cairo_font_slant_t>(slant),
      static_cast<cairo_font_weight_t>(weight));
}

void renderer::format_font(std::string const &family,
    font_slant slant,
    font_weight weight,
    double new_size)
{
  set_font_size(new_size);
  format_font(family, slant, weight);
}

void renderer::set_text_rotation(double degrees)
{
  // convert the given angle to rad
  rotation_angle = -degrees * M_PI / 180;
}

void renderer::set_horiz_text_just(text_just horiz_just)
{
  if (horiz_just != text_just::top && horiz_just != text_just::bottom)
    horiz_text_just = horiz_just;
}

void renderer::set_vert_text_just(text_just vert_just)
{
  if (vert_just != text_just::right && vert_just != text_just::left)
    vert_text_just = vert_just;
}

void renderer::draw_line(point2d start, point2d end)
{
  if(rectangle_off_screen({start, end}))
    return;

  if(current_coordinate_system == WORLD) {
    start = m_transform(start);
    end = m_transform(end);
  }

#ifdef EZGL_USE_X11
  if(!transparency_flag && x11_display != nullptr) {
    XDrawLine(x11_display, x11_drawable, x11_context, start.x, start.y, end.x, end.y);
    return;
  }
#endif

  cairo_move_to(m_cairo, start.x, start.y);
  cairo_line_to(m_cairo, end.x, end.y);

  cairo_stroke(m_cairo);
}

void renderer::draw_rectangle(point2d start, point2d end)
{
  if(rectangle_off_screen({start, end}))
    return;

  draw_rectangle_path(start, end, false);
}

void renderer::draw_rectangle(point2d start, double width, double height)
{
  if(rectangle_off_screen({start, {start.x + width, start.y + height}}))
    return;

  draw_rectangle_path(start, {start.x + width, start.y + height}, false);
}

void renderer::draw_rectangle(rectangle r)
{
  if(rectangle_off_screen({{r.left(), r.bottom()}, {r.right(), r.top()}}))
    return;

  draw_rectangle_path({r.left(), r.bottom()}, {r.right(), r.top()}, false);
}

void renderer::fill_rectangle(point2d start, point2d end)
{
  if(rectangle_off_screen({start, end}))
    return;

  draw_rectangle_path(start, end, true);
}

void renderer::fill_rectangle(point2d start, double width, double height)
{
  if(rectangle_off_screen({start, {start.x + width, start.y + height}}))
    return;

  draw_rectangle_path(start, {start.x + width, start.y + height}, true);
}

void renderer::fill_rectangle(rectangle r)
{
  if(rectangle_off_screen({{r.left(), r.bottom()}, {r.right(), r.top()}}))
    return;

  draw_rectangle_path({r.left(), r.bottom()}, {r.right(), r.top()}, true);
}

// For speed, use a fixed size polygon point buffer when possible
// Dynamically allocate an arbitrary size buffer only when necessary.
#define X11_MAX_FIXED_POLY_PTS 100

void renderer::fill_poly(std::vector<point2d> const &points)
{
  assert(points.size() > 1);

  // Conservative but fast clip test -- check containing rectangle of polygon
  double x_min = points[0].x;
  double x_max = points[0].x;
  double y_min = points[0].y;
  double y_max = points[0].y;

  for(std::size_t i = 1; i < points.size(); ++i) {
    x_min = std::min(x_min, points[i].x);
    x_max = std::max(x_max, points[i].x);
    y_min = std::min(y_min, points[i].y);
    y_max = std::max(y_max, points[i].y);
  }

  if(rectangle_off_screen({{x_min, y_min}, {x_max, y_max}}))
    return;

  point2d next_point = points[0];

#ifdef EZGL_USE_X11
  if(!transparency_flag && x11_display != nullptr) {
    XPoint fixed_trans_points[X11_MAX_FIXED_POLY_PTS];
    XPoint *trans_points = fixed_trans_points;

    if(points.size() > X11_MAX_FIXED_POLY_PTS) {
      trans_points = new XPoint[points.size()];
    }

    for(size_t i = 0; i < points.size(); i++) {
      if(current_coordinate_system == WORLD)
        next_point = m_transform(points[i]);
      else
        next_point = points[i];
      trans_points[i].x = static_cast<long>(next_point.x);
      trans_points[i].y = static_cast<long>(next_point.y);
    }

    XFillPolygon(x11_display, x11_drawable, x11_context, trans_points, points.size(), Complex,
        CoordModeOrigin);

    if(points.size() > X11_MAX_FIXED_POLY_PTS)
      delete[] trans_points;
    return;
  }
#endif

  if(current_coordinate_system == WORLD)
    next_point = m_transform(points[0]);

  cairo_move_to(m_cairo, next_point.x, next_point.y);

  for(std::size_t i = 1; i < points.size(); ++i) {
    if(current_coordinate_system == WORLD)
      next_point = m_transform(points[i]);
    else
      next_point = points[i];
    cairo_line_to(m_cairo, next_point.x, next_point.y);
  }

  cairo_close_path(m_cairo);
  cairo_fill(m_cairo);
}

void renderer::draw_elliptic_arc(point2d center,
    double radius_x,
    double radius_y,
    double start_angle,
    double extent_angle)
{
  if(rectangle_off_screen(
         {{center.x - radius_x, center.y - radius_y}, {center.x + radius_x, center.y + radius_y}}))
    return;

  // define the stretch factor (i.e. An ellipse is a stretched circle)
  double stretch_factor = radius_y / radius_x;

  draw_arc_path(center, radius_x, start_angle, extent_angle, stretch_factor, false);
}

void renderer::draw_arc(point2d center, double radius, double start_angle, double extent_angle)
{
  if(rectangle_off_screen(
         {{center.x - radius, center.y - radius}, {center.x + radius, center.y + radius}}))
    return;

  draw_arc_path(center, radius, start_angle, extent_angle, 1, false);
}

void renderer::fill_elliptic_arc(point2d center,
    double radius_x,
    double radius_y,
    double start_angle,
    double extent_angle)
{
  if(rectangle_off_screen(
         {{center.x - radius_x, center.y - radius_y}, {center.x + radius_x, center.y + radius_y}}))
    return;

  // define the stretch factor (i.e. An ellipse is a stretched circle)
  double stretch_factor = radius_y / radius_x;

  draw_arc_path(center, radius_x, start_angle, extent_angle, stretch_factor, true);
}

void renderer::fill_arc(point2d center, double radius, double start_angle, double extent_angle)
{
  if(rectangle_off_screen(
         {{center.x - radius, center.y - radius}, {center.x + radius, center.y + radius}}))
    return;

  draw_arc_path(center, radius, start_angle, extent_angle, 1, true);
}

void renderer::draw_text(point2d point, std::string const &text)
{
  // call the draw_text function with no bounds
  draw_text(point, text, DBL_MAX, DBL_MAX);
}

void renderer::draw_text(point2d point, std::string const &text, double bound_x, double bound_y)
{
  // the center point of the text
  point2d center = point;

  // roughly calculate the center point for pre-clipping
  if (horiz_text_just == text_just::left)
    center.x += bound_x/2;
  else if (horiz_text_just == text_just::right)
    center.x -= bound_x/2;
  if (vert_text_just == text_just::top)
    center.y -= bound_y/2;
  else if (vert_text_just == text_just::bottom)
    center.y += bound_y/2;

  if(rectangle_off_screen({{center.x - bound_x / 2, center.y - bound_y / 2}, bound_x, bound_y}))
    return;

  // get the width and height of the drawn text
  cairo_text_extents_t text_extents{};
  cairo_text_extents(m_cairo, text.c_str(), &text_extents);

  // get more information about the font used
  cairo_font_extents_t font_extents{};
  cairo_font_extents(m_cairo, &font_extents);

  // get text width and height in world coordinates (text width and height are constant in widget coordinates)
  double scaled_width = text_extents.width * m_camera->get_world_scale_factor().x;
  double scaled_height = text_extents.height * m_camera->get_world_scale_factor().y;

  // if text width or height is greater than the given bounds, don't draw the text.
  // NOTE: text rotation is NOT taken into account in bounding check (i.e. text width is compared to bound_x)
  if(scaled_width > bound_x || scaled_height > bound_y) {
    return;
  }

  // save the current state to undo the rotation needed for drawing rotated text
  cairo_save(m_cairo);

  // transform the given point
  if(current_coordinate_system == WORLD)
    center = m_transform(point);
  else
    center = point;

  // calculating the reference point to center the text around "center" taking into account the rotation_angle
  // for more info about reference point location: see https://www.cairographics.org/tutorial/#L1understandingtext
  point2d ref_point = {0, 0};

  ref_point.x = center.x -
                (text_extents.x_bearing + (text_extents.width / 2)) * cos(rotation_angle) -
                (-font_extents.descent + (text_extents.height / 2)) * sin(rotation_angle);

  ref_point.y = center.y -
                (text_extents.y_bearing + (text_extents.height / 2)) * cos(rotation_angle) -
                (text_extents.x_bearing + (text_extents.width / 2)) * sin(rotation_angle);

  // adjust the reference point according to the required justification
  if (horiz_text_just == text_just::left) {
    ref_point.x += (text_extents.width / 2) * cos(rotation_angle);
    ref_point.y += (text_extents.width / 2) * sin(rotation_angle);
  }
  else if (horiz_text_just == text_just::right) {
    ref_point.x -= (text_extents.width / 2) * cos(rotation_angle);
    ref_point.y -= (text_extents.width / 2) * sin(rotation_angle);
  }
  if (vert_text_just == text_just::top) {
    ref_point.x -= (text_extents.height / 2) * sin(rotation_angle);
    ref_point.y += (text_extents.height / 2) * cos(rotation_angle);
  }
  else if (vert_text_just == text_just::bottom) {
    ref_point.x += (text_extents.height / 2) * sin(rotation_angle);
    ref_point.y -= (text_extents.height / 2) * cos(rotation_angle);
  }

  // move to the reference point, perform the rotation, and draw the text
  cairo_move_to(m_cairo, ref_point.x, ref_point.y);
  cairo_rotate(m_cairo, rotation_angle);
  cairo_show_text(m_cairo, text.c_str());

  // restore the old state to undo the performed rotation
  cairo_restore(m_cairo);
}

void renderer::draw_rectangle_path(point2d start, point2d end, bool fill_flag)
{
  if(current_coordinate_system == WORLD) {
    start = m_transform(start);
    end = m_transform(end);
  }

#ifdef EZGL_USE_X11
  if(!transparency_flag && x11_display != nullptr) {
    // Add 0.5 for extra half-pixel accuracy
    int start_x = static_cast<int>(start.x + 0.5);
    int start_y = static_cast<int>(start.y + 0.5);
    int end_x = static_cast<int>(end.x + 0.5);
    int end_y = static_cast<int>(end.y + 0.5);

    if(fill_flag)
      XFillRectangle(x11_display, x11_drawable, x11_context, std::min(start_x, end_x),
          std::min(start_y, end_y), std::abs(end_x - start_x), std::abs(end_y - start_y));
    else
      XDrawRectangle(x11_display, x11_drawable, x11_context, std::min(start_x, end_x),
          std::min(start_y, end_y), std::abs(end_x - start_x), std::abs(end_y - start_y));
    return;
  }
#endif

  cairo_move_to(m_cairo, start.x, start.y);
  cairo_line_to(m_cairo, start.x, end.y);
  cairo_line_to(m_cairo, end.x, end.y);
  cairo_line_to(m_cairo, end.x, start.y);

  cairo_close_path(m_cairo);

  // actual drawing
  if(fill_flag)
    cairo_fill(m_cairo);
  else
    cairo_stroke(m_cairo);
}

void renderer::draw_arc_path(point2d center,
    double radius,
    double start_angle,
    double extent_angle,
    double stretch_factor,
    bool fill_flag)
{
  // point_x is a point on the arc outline
  point2d point_x = {center.x + radius, center.y};

  // transform the center point of the arc, and the other point
  if(current_coordinate_system == WORLD) {
    center = m_transform(center);
    point_x = m_transform(point_x);
  }

  // calculate the new radius after transforming to the new coordinates
  radius = point_x.x - center.x;

#ifdef EZGL_USE_X11
  if(!transparency_flag && x11_display != nullptr) {
    if(fill_flag)
      XFillArc(x11_display, x11_drawable, x11_context, center.x - radius,
          center.y - radius * stretch_factor, 2 * radius, 2 * radius * stretch_factor,
          start_angle * 64, extent_angle * 64);
    else
      XDrawArc(x11_display, x11_drawable, x11_context, center.x - radius,
          center.y - radius * stretch_factor, 2 * radius, 2 * radius * stretch_factor,
          start_angle * 64, extent_angle * 64);
    return;
  }
#endif

  // save the current state to undo the scaling needed for drawing ellipse
  cairo_save(m_cairo);

  // scale the drawing by the stretch factor to draw elliptic circles
  cairo_scale(m_cairo, 1 / stretch_factor, 1);
  center.x = center.x * stretch_factor;
  radius = radius * stretch_factor;

  // start a new path (forget the current point). Alternative for cairo_move_to() for drawing non-filled arc
  cairo_new_path(m_cairo);

  // if the arc will be filled in, start drawing from the center of the arc
  if(fill_flag)
    cairo_move_to(m_cairo, center.x, center.y);

  // calculating the ending angle
  double end_angle = start_angle + extent_angle;

  // draw the arc in counter clock-wise direction if the extent angle is positive
  if(extent_angle >= 0) {
    cairo_arc_negative(
        m_cairo, center.x, center.y, radius, -start_angle * M_PI / 180, -end_angle * M_PI / 180);
  }
  // draw the arc in clock-wise direction if the extent angle is negative
  else {
    cairo_arc(
        m_cairo, center.x, center.y, radius, -start_angle * M_PI / 180, -end_angle * M_PI / 180);
  }

  // if the arc will be filled in, return back to the center of the arc
  if(fill_flag)
    cairo_close_path(m_cairo);

  // restore the old state to undo the scaling needed for drawing ellipse
  cairo_restore(m_cairo);

  // actual drawing
  if(fill_flag)
    cairo_fill(m_cairo);
  else
    cairo_stroke(m_cairo);
}

void renderer::draw_surface(surface *p_surface, point2d top_left)
{
  // Check if the surface is properly created
  if(cairo_surface_status(p_surface) != CAIRO_STATUS_SUCCESS)
    return;

  // pre-clipping
  double s_width = (double)cairo_image_surface_get_width(p_surface);
  double s_height = (double)cairo_image_surface_get_height(p_surface);

  if(rectangle_off_screen({{top_left.x, top_left.y - s_height}, s_width, s_height}))
    return;

  // transform the given top_left point
  if(current_coordinate_system == WORLD)
    top_left = m_transform(top_left);

  // Create a source for painting from the surface
  cairo_set_source_surface(m_cairo, p_surface, top_left.x, top_left.y);

  // Actual drawing
  cairo_paint(m_cairo);
}

surface *renderer::load_png(const char *file_path)
{
  // Create an image surface from a PNG image
  cairo_surface_t *png_surface = cairo_image_surface_create_from_png(file_path);

  return png_surface;
}

void renderer::free_surface(surface *p_surface)
{
  // Check if the surface is properly created
  if (cairo_surface_status(p_surface) == CAIRO_STATUS_SUCCESS)
    cairo_surface_destroy(p_surface);
}
}
