/*
 * Copyright 2017 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.
 */

#ifndef LIB_TXT_SRC_PARAGRAPH_TXT_H_
#define LIB_TXT_SRC_PARAGRAPH_TXT_H_

#include <set>
#include <utility>
#include <vector>

#include "flutter/fml/compiler_specific.h"
#include "flutter/fml/macros.h"
#include "font_collection.h"
#include "line_metrics.h"
#include "minikin/LineBreaker.h"
#include "paint_record.h"
#include "paragraph.h"
#include "paragraph_style.h"
#include "placeholder_run.h"
#include "run_metrics.h"
#include "styled_runs.h"
#include "third_party/googletest/googletest/include/gtest/gtest_prod.h"  // nogncheck
#include "third_party/skia/include/core/SkFontMetrics.h"
#include "third_party/skia/include/core/SkRect.h"
#include "utils/LinuxUtils.h"
#include "utils/MacUtils.h"
#include "utils/WindowsUtils.h"

namespace txt {

using GlyphID = uint32_t;

// Constant with the unicode codepoint for the "Object replacement character".
// Used as a stand-in character for Placeholder boxes.
const int objReplacementChar = 0xFFFC;
// Constant with the unicode codepoint for the "Replacement character". This is
// the character that commonly renders as a black diamond with a white question
// mark. Used to replace non-placeholder instances of 0xFFFC in the text buffer.
const int replacementChar = 0xFFFD;

// Paragraph provides Layout, metrics, and painting capabilities for text. Once
// a Paragraph is constructed with ParagraphBuilder::Build(), an example basic
// workflow can be this:
//
//   std::unique_ptr<Paragraph> paragraph = paragraph_builder.Build();
//   paragraph->Layout(<somewidthgoeshere>);
//   paragraph->Paint(<someSkCanvas>, <xpos>, <ypos>);
class ParagraphTxt : public Paragraph {
 public:
  // Constructor. It is highly recommended to construct a paragraph with a
  // ParagraphBuilder.
  ParagraphTxt();

  virtual ~ParagraphTxt();

  // Minikin Layout doLayout() and LineBreaker addStyleRun() has an
  // O(N^2) (according to benchmarks) time complexity where N is the total
  // number of characters. However, this is not significant for reasonably sized
  // paragraphs. It is currently recommended to break up very long paragraphs
  // (10k+ characters) to ensure speedy layout.
  virtual void Layout(double width) override;

  virtual void Paint(SkCanvas* canvas, double x, double y) override;
  virtual bool Paint(flutter::DisplayListBuilder* builder,
                     double x,
                     double y) override {
    return false;
  }

  // Getter for paragraph_style_.
  const ParagraphStyle& GetParagraphStyle() const;

  // Returns the number of characters/unicode characters. AKA text_.size()
  size_t TextSize() const;

  double GetHeight() override;

  double GetMaxWidth() override;

  double GetLongestLine() override;

  double GetAlphabeticBaseline() override;

  double GetIdeographicBaseline() override;

  double GetMaxIntrinsicWidth() override;

  // Currently, calculated similarly to as GetLayoutWidth(), however this is not
  // necessarily 100% correct in all cases.
  double GetMinIntrinsicWidth() override;

  std::vector<TextBox> GetRectsForRange(
      size_t start,
      size_t end,
      RectHeightStyle rect_height_style,
      RectWidthStyle rect_width_style) override;

  PositionWithAffinity GetGlyphPositionAtCoordinate(double dx,
                                                    double dy) override;

  std::vector<Paragraph::TextBox> GetRectsForPlaceholders() override;

  Range<size_t> GetWordBoundary(size_t offset) override;

  // Returns the number of lines the paragraph takes up. If the text exceeds the
  // amount width and maxlines provides, Layout() truncates the extra text from
  // the layout and this will return the max lines allowed.
  size_t GetLineCount();

  bool DidExceedMaxLines() override;

  // Gets the full vector of LineMetrics which includes detailed data on each
  // line in the final layout.
  std::vector<LineMetrics>& GetLineMetrics() override;

  // Sets the needs_layout_ to dirty. When Layout() is called, a new Layout will
  // be performed when this is set to true. Can also be used to prevent a new
  // Layout from being calculated by setting to false.
  void SetDirty(bool dirty = true);

 private:
  friend class ParagraphBuilderTxt;
  FRIEND_TEST(ParagraphTest, SimpleParagraph);
  FRIEND_TEST(ParagraphTest, SimpleParagraphSmall);
  FRIEND_TEST(ParagraphTest, SimpleRedParagraph);
  FRIEND_TEST(ParagraphTest, RainbowParagraph);
  FRIEND_TEST(ParagraphTest, DefaultStyleParagraph);
  FRIEND_TEST(ParagraphTest, BoldParagraph);
  FRIEND_TEST_WINDOWS_DISABLED(ParagraphTest, LeftAlignParagraph);
  FRIEND_TEST_WINDOWS_DISABLED(ParagraphTest, RightAlignParagraph);
  FRIEND_TEST_WINDOWS_DISABLED(ParagraphTest, CenterAlignParagraph);
  FRIEND_TEST_WINDOWS_DISABLED(ParagraphTest, JustifyAlignParagraph);
  FRIEND_TEST_WINDOWS_DISABLED(ParagraphTest, JustifyRTL);
  FRIEND_TEST_WINDOWS_DISABLED(ParagraphTest, InlinePlaceholderLongestLine);
  FRIEND_TEST_LINUX_ONLY(ParagraphTest, JustifyRTLNewLine);
  FRIEND_TEST(ParagraphTest, DecorationsParagraph);
  FRIEND_TEST(ParagraphTest, ItalicsParagraph);
  FRIEND_TEST(ParagraphTest, ChineseParagraph);
  FRIEND_TEST(ParagraphTest, DISABLED_ArabicParagraph);
  FRIEND_TEST(ParagraphTest, SpacingParagraph);
  FRIEND_TEST(ParagraphTest, LongWordParagraph);
  FRIEND_TEST_LINUX_ONLY(ParagraphTest, KernScaleParagraph);
  FRIEND_TEST_WINDOWS_DISABLED(ParagraphTest, NewlineParagraph);
  FRIEND_TEST_LINUX_ONLY(ParagraphTest, EmojiParagraph);
  FRIEND_TEST_LINUX_ONLY(ParagraphTest, EmojiMultiLineRectsParagraph);
  FRIEND_TEST(ParagraphTest, HyphenBreakParagraph);
  FRIEND_TEST(ParagraphTest, RepeatLayoutParagraph);
  FRIEND_TEST(ParagraphTest, Ellipsize);
  FRIEND_TEST(ParagraphTest, UnderlineShiftParagraph);
  FRIEND_TEST(ParagraphTest, WavyDecorationParagraph);
  FRIEND_TEST(ParagraphTest, SimpleShadow);
  FRIEND_TEST(ParagraphTest, ComplexShadow);
  FRIEND_TEST(ParagraphTest, FontFallbackParagraph);
  FRIEND_TEST(ParagraphTest, InlinePlaceholder0xFFFCParagraph);
  FRIEND_TEST(ParagraphTest, FontFeaturesParagraph);
  FRIEND_TEST(ParagraphTest, GetGlyphPositionAtCoordinateSegfault);
  FRIEND_TEST(ParagraphTest, KhmerLineBreaker);
  FRIEND_TEST(ParagraphTest, TextHeightBehaviorRectsParagraph);

  // Starting data to layout.
  std::vector<uint16_t> text_;
  // A vector of PlaceholderRuns, which detail the sizes, positioning and break
  // behavior of the empty spaces to leave. Each placeholder span corresponds to
  // a 0xFFFC (object replacement character) in text_, which indicates the
  // position in the text where the placeholder will occur. There should be an
  // equal number of 0xFFFC characters and elements in this vector.
  std::vector<PlaceholderRun> inline_placeholders_;
  // The indexes of the boxes that correspond to an inline placeholder.
  std::vector<size_t> inline_placeholder_boxes_;
  // The indexes of instances of 0xFFFC that correspond to placeholders. This is
  // necessary since the user may pass in manually entered 0xFFFC values using
  // AddText().
  std::unordered_set<size_t> obj_replacement_char_indexes_;
  StyledRuns runs_;
  ParagraphStyle paragraph_style_;
  std::shared_ptr<FontCollection> font_collection_;

  minikin::LineBreaker breaker_;
  mutable std::unique_ptr<icu::BreakIterator> word_breaker_;

  std::vector<LineMetrics> line_metrics_;
  size_t final_line_count_ = 0;
  std::vector<double> line_widths_;

  // Stores the result of Layout().
  std::vector<PaintRecord> records_;

  bool did_exceed_max_lines_;

  // Strut metrics of zero will have no effect on the layout.
  struct StrutMetrics {
    double ascent = 0;  // Positive value to keep signs clear.
    double descent = 0;
    double leading = 0;
    double half_leading = 0;
    double line_height = 0;
    bool force_strut = false;
  };

  StrutMetrics strut_;

  // Overall left and right extremes over all lines.
  double max_right_;
  double min_left_;

  class BidiRun {
   public:
    // Constructs a BidiRun with is_ghost defaulted to false.
    BidiRun(size_t s, size_t e, TextDirection d, const TextStyle& st)
        : start_(s), end_(e), direction_(d), style_(&st), is_ghost_(false) {}

    // Constructs a BidiRun with a custom is_ghost flag.
    BidiRun(size_t s,
            size_t e,
            TextDirection d,
            const TextStyle& st,
            bool is_ghost)
        : start_(s), end_(e), direction_(d), style_(&st), is_ghost_(is_ghost) {}

    // Constructs a placeholder bidi run.
    BidiRun(size_t s,
            size_t e,
            TextDirection d,
            const TextStyle& st,
            PlaceholderRun& placeholder)
        : start_(s),
          end_(e),
          direction_(d),
          style_(&st),
          is_ghost_(false),
          placeholder_run_(&placeholder) {}

    size_t start() const { return start_; }
    size_t end() const { return end_; }
    size_t size() const { return end_ - start_; }
    TextDirection direction() const { return direction_; }
    const TextStyle& style() const { return *style_; }
    PlaceholderRun* placeholder_run() const { return placeholder_run_; }
    bool is_rtl() const { return direction_ == TextDirection::rtl; }
    // Tracks if the run represents trailing whitespace.
    bool is_ghost() const { return is_ghost_; }
    bool is_placeholder_run() const { return placeholder_run_ != nullptr; }

   private:
    size_t start_, end_;
    TextDirection direction_;
    const TextStyle* style_;
    bool is_ghost_;
    PlaceholderRun* placeholder_run_ = nullptr;
  };

  struct GlyphPosition {
    Range<size_t> code_units;
    Range<double> x_pos;

    GlyphPosition(double x_start,
                  double x_advance,
                  size_t code_unit_index,
                  size_t code_unit_width);

    void Shift(double delta);
  };

  struct GlyphLine {
    // Glyph positions sorted by x coordinate.
    const std::vector<GlyphPosition> positions;
    const size_t total_code_units;

    GlyphLine(std::vector<GlyphPosition>&& p, size_t tcu);
  };

  struct CodeUnitRun {
    // Glyph positions sorted by code unit index.
    std::vector<GlyphPosition> positions;
    Range<size_t> code_units;
    Range<double> x_pos;
    size_t line_number;
    SkFontMetrics font_metrics;
    const TextStyle* style;
    TextDirection direction;
    const PlaceholderRun* placeholder_run;

    CodeUnitRun(std::vector<GlyphPosition>&& p,
                Range<size_t> cu,
                Range<double> x,
                size_t line,
                const SkFontMetrics& metrics,
                const TextStyle& st,
                TextDirection dir,
                const PlaceholderRun* placeholder);

    void Shift(double delta);
  };

  // Holds the laid out x positions of each glyph.
  std::vector<GlyphLine> glyph_lines_;

  // Holds the positions of each range of code units in the text.
  // Sorted in code unit index order.
  std::vector<CodeUnitRun> code_unit_runs_;
  // Holds the positions of the inline placeholders.
  std::vector<CodeUnitRun> inline_placeholder_code_unit_runs_;

  // The max width of the paragraph as provided in the most recent Layout()
  // call.
  double width_ = -1.0f;
  double longest_line_ = -1.0f;
  double max_intrinsic_width_ = 0;
  double min_intrinsic_width_ = 0;
  double alphabetic_baseline_ = std::numeric_limits<double>::max();
  double ideographic_baseline_ = std::numeric_limits<double>::max();

  bool needs_layout_ = true;

  struct WaveCoordinates {
    double x_start;
    double y_start;
    double x_end;
    double y_end;

    WaveCoordinates(double x_s, double y_s, double x_e, double y_e)
        : x_start(x_s), y_start(y_s), x_end(x_e), y_end(y_e) {}
  };

  // Passes in the text and Styled Runs. text_ and runs_ will later be passed
  // into breaker_ in InitBreaker(), which is called in Layout().
  void SetText(std::vector<uint16_t> text, StyledRuns runs);

  void SetParagraphStyle(const ParagraphStyle& style);

  void SetFontCollection(std::shared_ptr<FontCollection> font_collection);

  void SetInlinePlaceholders(
      std::vector<PlaceholderRun> inline_placeholders,
      std::unordered_set<size_t> obj_replacement_char_indexes);

  // Break the text into lines.
  bool ComputeLineBreaks();

  // Break the text into runs based on LTR/RTL text direction.
  bool ComputeBidiRuns(std::vector<BidiRun>* result);

  // Calculates and populates strut based on paragraph_style_ strut info.
  void ComputeStrut(StrutMetrics* strut, SkFont& font);

  // Adjusts the ascent and descent based on the existence and type of
  // placeholder. This method sets the proper metrics to achieve the different
  // PlaceholderAlignment options.
  void ComputePlaceholder(PlaceholderRun* placeholder_run,
                          double& ascent,
                          double& descent);

  bool IsStrutValid() const;

  void UpdateLineMetrics(const SkFontMetrics& metrics,
                         const TextStyle& style,
                         double& max_ascent,
                         double& max_descent,
                         double& max_unscaled_ascent,
                         PlaceholderRun* placeholder_run,
                         size_t line_number,
                         size_t line_limit);

  // Calculate the starting X offset of a line based on the line's width and
  // alignment.
  double GetLineXOffset(double line_total_advance, bool justify_line);

  // Creates and draws the decorations onto the canvas.
  void PaintDecorations(SkCanvas* canvas,
                        const PaintRecord& record,
                        SkPoint base_offset);

  // Computes the beziers for a wavy decoration. The results will be
  // applied to path.
  void ComputeWavyDecoration(SkPath& path,
                             double x,
                             double y,
                             double width,
                             double thickness);

  // Draws the background onto the canvas.
  void PaintBackground(SkCanvas* canvas,
                       const PaintRecord& record,
                       SkPoint base_offset);

  // Draws the shadows onto the canvas.
  void PaintShadow(SkCanvas* canvas, const PaintRecord& record, SkPoint offset);

  // Obtain a Minikin font collection matching this text style.
  std::shared_ptr<minikin::FontCollection> GetMinikinFontCollectionForStyle(
      const TextStyle& style);

  // Get a default SkTypeface for a text style.
  sk_sp<SkTypeface> GetDefaultSkiaTypeface(const TextStyle& style);

  FML_DISALLOW_COPY_AND_ASSIGN(ParagraphTxt);
};

}  // namespace txt

#endif  // LIB_TXT_SRC_PARAGRAPH_TXT_H_
