/*
 * Copyright 2019 Google Inc.
 *
 * 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 "paragraph_skia.h"

#include <algorithm>
#include <numeric>

namespace txt {

namespace skt = skia::textlayout;

namespace {

// Convert SkFontStyle::Weight values (ranging from 100-900) to txt::FontWeight
// values (ranging from 0-8).
txt::FontWeight GetTxtFontWeight(int font_weight) {
  int txt_weight = (font_weight - 100) / 100;
  txt_weight = std::clamp(txt_weight, static_cast<int>(txt::FontWeight::w100),
                          static_cast<int>(txt::FontWeight::w900));
  return static_cast<txt::FontWeight>(txt_weight);
}

txt::FontStyle GetTxtFontStyle(SkFontStyle::Slant font_slant) {
  return font_slant == SkFontStyle::Slant::kUpright_Slant
             ? txt::FontStyle::normal
             : txt::FontStyle::italic;
}

TextStyle SkiaToTxt(const skt::TextStyle& skia) {
  TextStyle txt;

  txt.color = skia.getColor();
  txt.decoration = static_cast<TextDecoration>(skia.getDecorationType());
  txt.decoration_color = skia.getDecorationColor();
  txt.decoration_style =
      static_cast<TextDecorationStyle>(skia.getDecorationStyle());
  txt.decoration_thickness_multiplier =
      SkScalarToDouble(skia.getDecorationThicknessMultiplier());
  txt.font_weight = GetTxtFontWeight(skia.getFontStyle().weight());
  txt.font_style = GetTxtFontStyle(skia.getFontStyle().slant());

  txt.text_baseline = static_cast<TextBaseline>(skia.getTextBaseline());

  for (const SkString& font_family : skia.getFontFamilies()) {
    txt.font_families.emplace_back(font_family.c_str());
  }

  txt.font_size = SkScalarToDouble(skia.getFontSize());
  txt.letter_spacing = SkScalarToDouble(skia.getLetterSpacing());
  txt.word_spacing = SkScalarToDouble(skia.getWordSpacing());
  txt.height = SkScalarToDouble(skia.getHeight());

  txt.locale = skia.getLocale().c_str();
  if (skia.hasBackground()) {
    txt.background = skia.getBackground();
  }
  if (skia.hasForeground()) {
    txt.foreground = skia.getForeground();
  }

  txt.text_shadows.clear();
  for (const skt::TextShadow& skia_shadow : skia.getShadows()) {
    txt::TextShadow shadow;
    shadow.offset = skia_shadow.fOffset;
    shadow.blur_sigma = skia_shadow.fBlurSigma;
    shadow.color = skia_shadow.fColor;
    txt.text_shadows.emplace_back(shadow);
  }

  return txt;
}

}  // anonymous namespace

ParagraphSkia::ParagraphSkia(std::unique_ptr<skt::Paragraph> paragraph)
    : paragraph_(std::move(paragraph)) {}

double ParagraphSkia::GetMaxWidth() {
  return SkScalarToDouble(paragraph_->getMaxWidth());
}

double ParagraphSkia::GetHeight() {
  return SkScalarToDouble(paragraph_->getHeight());
}

double ParagraphSkia::GetLongestLine() {
  return SkScalarToDouble(paragraph_->getLongestLine());
}

std::vector<LineMetrics>& ParagraphSkia::GetLineMetrics() {
  if (!line_metrics_) {
    std::vector<skt::LineMetrics> metrics;
    paragraph_->getLineMetrics(metrics);

    line_metrics_.emplace();
    line_metrics_styles_.reserve(
        std::accumulate(metrics.begin(), metrics.end(), 0,
                        [](const int a, const skt::LineMetrics& b) {
                          return a + b.fLineMetrics.size();
                        }));

    for (const skt::LineMetrics& skm : metrics) {
      LineMetrics& txtm = line_metrics_->emplace_back(
          skm.fStartIndex, skm.fEndIndex, skm.fEndExcludingWhitespaces,
          skm.fEndIncludingNewline, skm.fHardBreak);
      txtm.ascent = skm.fAscent;
      txtm.descent = skm.fDescent;
      txtm.unscaled_ascent = skm.fUnscaledAscent;
      txtm.height = skm.fHeight;
      txtm.width = skm.fWidth;
      txtm.left = skm.fLeft;
      txtm.baseline = skm.fBaseline;
      txtm.line_number = skm.fLineNumber;

      for (const auto& sk_iter : skm.fLineMetrics) {
        const skt::StyleMetrics& sk_style_metrics = sk_iter.second;
        line_metrics_styles_.push_back(SkiaToTxt(*sk_style_metrics.text_style));
        txtm.run_metrics.emplace(
            std::piecewise_construct, std::forward_as_tuple(sk_iter.first),
            std::forward_as_tuple(&line_metrics_styles_.back(),
                                  sk_style_metrics.font_metrics));
      }
    }
  }

  return line_metrics_.value();
}

double ParagraphSkia::GetMinIntrinsicWidth() {
  return SkScalarToDouble(paragraph_->getMinIntrinsicWidth());
}

double ParagraphSkia::GetMaxIntrinsicWidth() {
  return SkScalarToDouble(paragraph_->getMaxIntrinsicWidth());
}

double ParagraphSkia::GetAlphabeticBaseline() {
  return SkScalarToDouble(paragraph_->getAlphabeticBaseline());
}

double ParagraphSkia::GetIdeographicBaseline() {
  return SkScalarToDouble(paragraph_->getIdeographicBaseline());
}

bool ParagraphSkia::DidExceedMaxLines() {
  return paragraph_->didExceedMaxLines();
}

void ParagraphSkia::Layout(double width) {
  paragraph_->layout(width);
}

void ParagraphSkia::Paint(SkCanvas* canvas, double x, double y) {
  paragraph_->paint(canvas, x, y);
}

std::vector<Paragraph::TextBox> ParagraphSkia::GetRectsForRange(
    size_t start,
    size_t end,
    RectHeightStyle rect_height_style,
    RectWidthStyle rect_width_style) {
  std::vector<skt::TextBox> skia_boxes = paragraph_->getRectsForRange(
      start, end, static_cast<skt::RectHeightStyle>(rect_height_style),
      static_cast<skt::RectWidthStyle>(rect_width_style));

  std::vector<Paragraph::TextBox> boxes;
  for (const skt::TextBox& skia_box : skia_boxes) {
    boxes.emplace_back(skia_box.rect,
                       static_cast<TextDirection>(skia_box.direction));
  }

  return boxes;
}

std::vector<Paragraph::TextBox> ParagraphSkia::GetRectsForPlaceholders() {
  std::vector<skt::TextBox> skia_boxes = paragraph_->getRectsForPlaceholders();

  std::vector<Paragraph::TextBox> boxes;
  for (const skt::TextBox& skia_box : skia_boxes) {
    boxes.emplace_back(skia_box.rect,
                       static_cast<TextDirection>(skia_box.direction));
  }

  return boxes;
}

Paragraph::PositionWithAffinity ParagraphSkia::GetGlyphPositionAtCoordinate(
    double dx,
    double dy) {
  skt::PositionWithAffinity skia_pos =
      paragraph_->getGlyphPositionAtCoordinate(dx, dy);

  return ParagraphSkia::PositionWithAffinity(
      skia_pos.position, static_cast<Affinity>(skia_pos.affinity));
}

Paragraph::Range<size_t> ParagraphSkia::GetWordBoundary(size_t offset) {
  skt::SkRange<size_t> range = paragraph_->getWordBoundary(offset);
  return Paragraph::Range<size_t>(range.start, range.end);
}

}  // namespace txt
