/*
 * 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();
}

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);
}
}
