// Copyright 2017 Google Inc. All Rights Reserved.
//
// 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.

#include "cobalt/renderer/rasterizer/egl/draw_rect_shadow_spread.h"

#include <GLES2/gl2.h>
#include <algorithm>

#include "base/logging.h"
#include "cobalt/renderer/backend/egl/utils.h"
#include "starboard/memory.h"

namespace cobalt {
namespace renderer {
namespace rasterizer {
namespace egl {

DrawRectShadowSpread::VertexAttributesSquare::VertexAttributesSquare(
    float x, float y, uint32_t in_color) {
  position[0] = x;
  position[1] = y;
  color = in_color;
}

DrawRectShadowSpread::VertexAttributesRound::VertexAttributesRound(
    float x, float y, const RCorner& inner, const RCorner& outer) {
  position[0] = x;
  position[1] = y;
  rcorner_inner = RCorner(position, inner);
  rcorner_outer = RCorner(position, outer);
}

DrawRectShadowSpread::DrawRectShadowSpread(GraphicsState* graphics_state,
    const BaseState& base_state, const math::RectF& inner_rect,
    const OptionalRoundedCorners& inner_corners, const math::RectF& outer_rect,
    const OptionalRoundedCorners& outer_corners,
    const render_tree::ColorRGBA& color)
    : DrawObject(base_state),
      vertex_buffer_(nullptr),
      index_buffer_(nullptr) {
  color_ = GetDrawColor(color) * base_state_.opacity;

  // Extract scale from the transform and move it into the vertex attributes
  // so that the anti-aliased edges remain 1 pixel wide.
  math::Vector2dF scale = RemoveScaleFromTransform();
  math::RectF inside_rect(inner_rect);
  math::RectF outside_rect(outer_rect);
  inside_rect.Scale(scale.x(), scale.y());
  outside_rect.Scale(scale.x(), scale.y());

  if (inner_corners || outer_corners) {
    // If using rounded corners, then both inner and outer rects must have
    // rounded corner definitions.
    DCHECK(inner_corners);
    DCHECK(outer_corners);
    render_tree::RoundedCorners inside_corners =
        inner_corners->Scale(scale.x(), scale.y());
    render_tree::RoundedCorners outside_corners =
        outer_corners->Scale(scale.x(), scale.y());
    SetGeometry(graphics_state,
                inside_rect, inside_corners,
                outside_rect, outside_corners);
  } else {
    SetGeometry(graphics_state, inside_rect, outside_rect);
  }
}

void DrawRectShadowSpread::ExecuteUpdateVertexBuffer(
    GraphicsState* graphics_state,
    ShaderProgramManager* program_manager) {
  if (attributes_square_.size() > 0) {
    vertex_buffer_ = graphics_state->AllocateVertexData(
        attributes_square_.size() * sizeof(attributes_square_[0]));
    SbMemoryCopy(vertex_buffer_, &attributes_square_[0],
        attributes_square_.size() * sizeof(attributes_square_[0]));
  } else if (attributes_round_.size() > 0) {
    vertex_buffer_ = graphics_state->AllocateVertexData(
        attributes_round_.size() * sizeof(attributes_round_[0]));
    SbMemoryCopy(vertex_buffer_, &attributes_round_[0],
        attributes_round_.size() * sizeof(attributes_round_[0]));
    index_buffer_ = graphics_state->AllocateVertexIndices(indices_.size());
    SbMemoryCopy(index_buffer_, &indices_[0],
        indices_.size() * sizeof(indices_[0]));
  }
}

void DrawRectShadowSpread::ExecuteRasterize(
    GraphicsState* graphics_state,
    ShaderProgramManager* program_manager) {
  if (vertex_buffer_ == nullptr) {
    return;
  }

  // Draw the box shadow.
  if (attributes_square_.size() > 0) {
    ShaderProgram<ShaderVertexColor,
                  ShaderFragmentColor>* program;
    program_manager->GetProgram(&program);
    graphics_state->UseProgram(program->GetHandle());
    SetupVertexShader(graphics_state, program->GetVertexShader());
    GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, attributes_square_.size()));
  } else {
    ShaderProgram<ShaderVertexRcorner2,
                  ShaderFragmentRcorner2Color>* program;
    program_manager->GetProgram(&program);
    graphics_state->UseProgram(program->GetHandle());
    SetupVertexShader(graphics_state, program->GetVertexShader());
    GL_CALL(glUniform4f(program->GetFragmentShader().u_color(),
        color_.r(), color_.g(), color_.b(), color_.a()));
    GL_CALL(glDrawElements(GL_TRIANGLES, indices_.size(), GL_UNSIGNED_SHORT,
        graphics_state->GetVertexIndexPointer(index_buffer_)));
  }
}

base::TypeId DrawRectShadowSpread::GetTypeId() const {
  if (attributes_square_.size() > 0) {
    return ShaderProgram<ShaderVertexColor,
                         ShaderFragmentColor>::GetTypeId();
  } else {
    return ShaderProgram<ShaderVertexRcorner2,
                         ShaderFragmentRcorner2Color>::GetTypeId();
  }
}

void DrawRectShadowSpread::SetupVertexShader(GraphicsState* graphics_state,
    const ShaderVertexColor& shader) {
  graphics_state->UpdateClipAdjustment(shader.u_clip_adjustment());
  graphics_state->UpdateTransformMatrix(shader.u_view_matrix(),
      base_state_.transform);
  graphics_state->Scissor(base_state_.scissor.x(), base_state_.scissor.y(),
      base_state_.scissor.width(), base_state_.scissor.height());
  graphics_state->VertexAttribPointer(
      shader.a_position(), 2, GL_FLOAT, GL_FALSE,
      sizeof(VertexAttributesSquare), vertex_buffer_ +
      offsetof(VertexAttributesSquare, position));
  graphics_state->VertexAttribPointer(
      shader.a_color(), 4, GL_UNSIGNED_BYTE, GL_TRUE,
      sizeof(VertexAttributesSquare), vertex_buffer_ +
      offsetof(VertexAttributesSquare, color));
  graphics_state->VertexAttribFinish();
}

void DrawRectShadowSpread::SetupVertexShader(GraphicsState* graphics_state,
    const ShaderVertexRcorner2& shader) {
  graphics_state->UpdateClipAdjustment(shader.u_clip_adjustment());
  graphics_state->UpdateTransformMatrix(shader.u_view_matrix(),
      base_state_.transform);
  graphics_state->Scissor(base_state_.scissor.x(), base_state_.scissor.y(),
      base_state_.scissor.width(), base_state_.scissor.height());
  graphics_state->VertexAttribPointer(
      shader.a_position(), 2, GL_FLOAT, GL_FALSE,
      sizeof(VertexAttributesRound), vertex_buffer_ +
      offsetof(VertexAttributesRound, position));
  graphics_state->VertexAttribPointer(
      shader.a_rcorner_inner(), 4, GL_FLOAT, GL_FALSE,
      sizeof(VertexAttributesRound), vertex_buffer_ +
      offsetof(VertexAttributesRound, rcorner_inner));
  graphics_state->VertexAttribPointer(
      shader.a_rcorner_outer(), 4, GL_FLOAT, GL_FALSE,
      sizeof(VertexAttributesRound), vertex_buffer_ +
      offsetof(VertexAttributesRound, rcorner_outer));
  graphics_state->VertexAttribFinish();
}

void DrawRectShadowSpread::SetGeometry(GraphicsState* graphics_state,
    const math::RectF& inner_rect, const math::RectF& outer_rect) {
  // Draw the box shadow's spread. This is a triangle strip covering the area
  // between outer rect and inner rect.
  uint32_t color = GetGLRGBA(color_);

  if (inner_rect.IsEmpty()) {
    attributes_square_.reserve(4);
    attributes_square_.emplace_back(
        outer_rect.x(), outer_rect.y(), color);
    attributes_square_.emplace_back(
        outer_rect.right(), outer_rect.y(), color);
    attributes_square_.emplace_back(
        outer_rect.x(), outer_rect.bottom(), color);
    attributes_square_.emplace_back(
        outer_rect.right(), outer_rect.bottom(), color);
  } else {
    math::RectF inside_rect(inner_rect);
    inside_rect.Intersect(outer_rect);
    attributes_square_.reserve(10);
    attributes_square_.emplace_back(
        outer_rect.x(), outer_rect.y(), color);
    attributes_square_.emplace_back(
        inside_rect.x(), inside_rect.y(), color);
    attributes_square_.emplace_back(
        outer_rect.right(), outer_rect.y(), color);
    attributes_square_.emplace_back(
        inside_rect.right(), inside_rect.y(), color);
    attributes_square_.emplace_back(
        outer_rect.right(), outer_rect.bottom(), color);
    attributes_square_.emplace_back(
        inside_rect.right(), inside_rect.bottom(), color);
    attributes_square_.emplace_back(
        outer_rect.x(), outer_rect.bottom(), color);
    attributes_square_.emplace_back(
        inside_rect.x(), inside_rect.bottom(), color);
    attributes_square_.emplace_back(
        outer_rect.x(), outer_rect.y(), color);
    attributes_square_.emplace_back(
        inside_rect.x(), inside_rect.y(), color);
  }

  graphics_state->ReserveVertexData(
      attributes_square_.size() * sizeof(attributes_square_[0]));
}

void DrawRectShadowSpread::SetGeometry(
    GraphicsState* graphics_state,
    const math::RectF& inner_rect,
    const render_tree::RoundedCorners& inner_corners,
    const math::RectF& outer_rect,
    const render_tree::RoundedCorners& outer_corners) {
  // Draw the area between the inner rounded rect and outer rounded rect. Add
  // a 1-pixel border to include antialiasing.
  math::RectF bounds(outer_rect);
  bounds.Outset(1.0f, 1.0f);

  // Get the render quads for the inner rounded rect excluding its inscribed
  // rectangle.
  RRectAttributes rrect_inner[8];
  GetRRectAttributes(bounds, inner_rect, inner_corners, rrect_inner);

  // Get the render quads for the outer rounded rect.
  RRectAttributes rrect_outer[4];
  GetRRectAttributes(bounds, outer_rect, outer_corners, rrect_outer);

  // Add geometry to draw the area between the inner rrect and outer rrect.
  for (int i = 0; i < arraysize(rrect_inner); ++i) {
    for (int o = 0; o < arraysize(rrect_outer); ++o) {
      math::RectF intersection = math::IntersectRects(
          rrect_inner[i].bounds, rrect_outer[o].bounds);
      if (!intersection.IsEmpty()) {
        // Use two triangles to draw the intersection.
        const RCorner& inner = rrect_inner[i].rcorner;
        const RCorner& outer = rrect_outer[o].rcorner;
        uint16_t vert = static_cast<uint16_t>(attributes_round_.size());
        attributes_round_.emplace_back(
            intersection.x(), intersection.y(), inner, outer);
        attributes_round_.emplace_back(
            intersection.right(), intersection.y(), inner, outer);
        attributes_round_.emplace_back(
            intersection.x(), intersection.bottom(), inner, outer);
        attributes_round_.emplace_back(
            intersection.right(), intersection.bottom(), inner, outer);
        indices_.emplace_back(vert);
        indices_.emplace_back(vert + 1);
        indices_.emplace_back(vert + 2);
        indices_.emplace_back(vert + 1);
        indices_.emplace_back(vert + 2);
        indices_.emplace_back(vert + 3);
      }
    }
  }

  graphics_state->ReserveVertexData(
      attributes_round_.size() * sizeof(attributes_round_[0]));
  graphics_state->ReserveVertexIndices(indices_.size());
}

}  // namespace egl
}  // namespace rasterizer
}  // namespace renderer
}  // namespace cobalt
