// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// @dart = 2.10
part of engine;

class CkParagraphStyle implements ui.ParagraphStyle {
  CkParagraphStyle({
    ui.TextAlign? textAlign,
    ui.TextDirection? textDirection,
    int? maxLines,
    String? fontFamily,
    double? fontSize,
    double? height,
    ui.TextHeightBehavior? textHeightBehavior,
    ui.FontWeight? fontWeight,
    ui.FontStyle? fontStyle,
    ui.StrutStyle? strutStyle,
    String? ellipsis,
    ui.Locale? locale,
  }) : skParagraphStyle = toSkParagraphStyle(
          textAlign,
          textDirection,
          maxLines,
          fontFamily,
          fontSize,
          height,
          textHeightBehavior,
          fontWeight,
          fontStyle,
          strutStyle,
          ellipsis,
          locale,
        ) {
    _textDirection = textDirection ?? ui.TextDirection.ltr;
    _fontFamily = fontFamily;
    _fontSize = fontSize;
    _fontWeight = fontWeight;
    _fontStyle = fontStyle;
  }

  SkParagraphStyle skParagraphStyle;
  ui.TextDirection? _textDirection;
  String? _fontFamily;
  double? _fontSize;
  ui.FontWeight? _fontWeight;
  ui.FontStyle? _fontStyle;

  static SkTextStyleProperties toSkTextStyleProperties(
    String? fontFamily,
    double? fontSize,
    ui.FontWeight? fontWeight,
    ui.FontStyle? fontStyle,
  ) {
    final SkTextStyleProperties skTextStyle = SkTextStyleProperties();
    if (fontWeight != null || fontStyle != null) {
      skTextStyle.fontStyle = toSkFontStyle(fontWeight, fontStyle);
    }

    if (fontSize != null) {
      skTextStyle.fontSize = fontSize;
    }

    if (fontFamily == null ||
        !skiaFontCollection.registeredFamilies.contains(fontFamily)) {
      fontFamily = 'Roboto';
    }
    skTextStyle.fontFamilies = [fontFamily];

    return skTextStyle;
  }

  static SkStrutStyleProperties toSkStrutStyleProperties(ui.StrutStyle value) {
    EngineStrutStyle style = value as EngineStrutStyle;
    final SkStrutStyleProperties skStrutStyle = SkStrutStyleProperties();
    if (style._fontFamily != null) {
      final List<String> fontFamilies = <String>[style._fontFamily!];
      if (style._fontFamilyFallback != null) {
        fontFamilies.addAll(style._fontFamilyFallback!);
      }
      skStrutStyle.fontFamilies = fontFamilies;
    } else {
      // If no strut font family is given, default to Roboto.
      skStrutStyle.fontFamilies = ['Roboto'];
    }

    if (style._fontSize != null) {
      skStrutStyle.fontSize = style._fontSize;
    }

    if (style._height != null) {
      skStrutStyle.heightMultiplier = style._height;
    }

    if (style._leading != null) {
      skStrutStyle.leading = style._leading;
    }

    if (style._fontWeight != null || style._fontStyle != null) {
      skStrutStyle.fontStyle =
          toSkFontStyle(style._fontWeight, style._fontStyle);
    }

    if (style._forceStrutHeight != null) {
      skStrutStyle.forceStrutHeight = style._forceStrutHeight;
    }

    skStrutStyle.strutEnabled = true;

    return skStrutStyle;
  }

  static SkParagraphStyle toSkParagraphStyle(
    ui.TextAlign? textAlign,
    ui.TextDirection? textDirection,
    int? maxLines,
    String? fontFamily,
    double? fontSize,
    double? height,
    ui.TextHeightBehavior? textHeightBehavior,
    ui.FontWeight? fontWeight,
    ui.FontStyle? fontStyle,
    ui.StrutStyle? strutStyle,
    String? ellipsis,
    ui.Locale? locale,
  ) {
    final SkParagraphStyleProperties properties = SkParagraphStyleProperties();

    if (textAlign != null) {
      properties.textAlign = toSkTextAlign(textAlign);
    }

    if (textDirection != null) {
      properties.textDirection = toSkTextDirection(textDirection);
    }

    if (maxLines != null) {
      properties.maxLines = maxLines;
    }

    if (height != null) {
      properties.heightMultiplier = height;
    }

    if (textHeightBehavior != null) {
      properties.textHeightBehavior = textHeightBehavior.encode();
    }

    if (ellipsis != null) {
      properties.ellipsis = ellipsis;
    }

    if (strutStyle != null) {
      properties.strutStyle = toSkStrutStyleProperties(strutStyle);
    }

    properties.textStyle =
        toSkTextStyleProperties(fontFamily, fontSize, fontWeight, fontStyle);

    return canvasKit.ParagraphStyle(properties);
  }

  CkTextStyle getTextStyle() {
    return CkTextStyle(
      fontFamily: _fontFamily,
      fontSize: _fontSize,
      fontWeight: _fontWeight,
      fontStyle: _fontStyle,
    );
  }
}

class CkTextStyle implements ui.TextStyle {
  SkTextStyle skTextStyle;

  ui.Color? color;
  ui.TextDecoration? decoration;
  ui.Color? decorationColor;
  ui.TextDecorationStyle? decorationStyle;
  double? decorationThickness;
  ui.FontWeight? fontWeight;
  ui.FontStyle? fontStyle;
  ui.TextBaseline? textBaseline;
  String? fontFamily;
  List<String>? fontFamilyFallback;
  double? fontSize;
  double? letterSpacing;
  double? wordSpacing;
  double? height;
  ui.Locale? locale;
  CkPaint? background;
  CkPaint? foreground;
  List<ui.Shadow>? shadows;
  List<ui.FontFeature>? fontFeatures;

  factory CkTextStyle({
    ui.Color? color,
    ui.TextDecoration? decoration,
    ui.Color? decorationColor,
    ui.TextDecorationStyle? decorationStyle,
    double? decorationThickness,
    ui.FontWeight? fontWeight,
    ui.FontStyle? fontStyle,
    ui.TextBaseline? textBaseline,
    String? fontFamily,
    List<String>? fontFamilyFallback,
    double? fontSize,
    double? letterSpacing,
    double? wordSpacing,
    double? height,
    ui.Locale? locale,
    CkPaint? background,
    CkPaint? foreground,
    List<ui.Shadow>? shadows,
    List<ui.FontFeature>? fontFeatures,
  }) {
    final SkTextStyleProperties properties = SkTextStyleProperties();

    if (background != null) {
      properties.backgroundColor = makeFreshSkColor(background.color);
    }

    if (color != null) {
      properties.color = makeFreshSkColor(color);
    }

    if (decoration != null) {
      int decorationValue = canvasKit.NoDecoration;
      if (decoration.contains(ui.TextDecoration.underline)) {
        decorationValue |= canvasKit.UnderlineDecoration;
      }
      if (decoration.contains(ui.TextDecoration.overline)) {
        decorationValue |= canvasKit.OverlineDecoration;
      }
      if (decoration.contains(ui.TextDecoration.lineThrough)) {
        decorationValue |= canvasKit.LineThroughDecoration;
      }
      properties.decoration = decorationValue;
    }

    if (decorationThickness != null) {
      properties.decorationThickness = decorationThickness;
    }

    if (decorationColor != null) {
      properties.decorationColor = makeFreshSkColor(decorationColor);
    }

    if (decorationStyle != null) {
      properties.decorationStyle = toSkTextDecorationStyle(decorationStyle);
    }

    if (textBaseline != null) {
      properties.textBaseline = toSkTextBaseline(textBaseline);
    }

    if (fontSize != null) {
      properties.fontSize = fontSize;
    }

    if (letterSpacing != null) {
      properties.letterSpacing = letterSpacing;
    }

    if (wordSpacing != null) {
      properties.wordSpacing = wordSpacing;
    }

    if (height != null) {
      properties.heightMultiplier = height;
    }

    if (locale != null) {
      properties.locale = locale.toLanguageTag();
    }

    if (fontFamily == null ||
        !skiaFontCollection.registeredFamilies.contains(fontFamily)) {
      fontFamily = 'Roboto';
    }

    List<String> fontFamilies = <String>[fontFamily];
    if (fontFamilyFallback != null &&
        !fontFamilyFallback.every((font) => fontFamily == font)) {
      fontFamilies.addAll(fontFamilyFallback);
    }

    properties.fontFamilies = fontFamilies;

    if (fontWeight != null || fontStyle != null) {
      properties.fontStyle = toSkFontStyle(fontWeight, fontStyle);
    }

    if (foreground != null) {
      properties.foregroundColor = makeFreshSkColor(foreground.color);
    }

    if (shadows != null) {
      List<SkTextShadow> ckShadows = <SkTextShadow>[];
      for (ui.Shadow shadow in shadows) {
        final ckShadow = SkTextShadow();
        ckShadow.color = makeFreshSkColor(shadow.color);
        ckShadow.offset = toSkPoint(shadow.offset);
        ckShadow.blurRadius = shadow.blurRadius;
        ckShadows.add(ckShadow);
      }
      properties.shadows = ckShadows;
    }

    if (fontFeatures != null) {
      List<SkFontFeature> ckFontFeatures = <SkFontFeature>[];
      for (ui.FontFeature fontFeature in fontFeatures) {
        SkFontFeature ckFontFeature = SkFontFeature();
        ckFontFeature.name = fontFeature.feature;
        ckFontFeature.value = fontFeature.value;
        ckFontFeatures.add(ckFontFeature);
      }
      properties.fontFeatures = ckFontFeatures;
    }

    return CkTextStyle._(
      canvasKit.TextStyle(properties),
      color,
      decoration,
      decorationColor,
      decorationStyle,
      decorationThickness,
      fontWeight,
      fontStyle,
      textBaseline,
      fontFamily,
      fontFamilyFallback,
      fontSize,
      letterSpacing,
      wordSpacing,
      height,
      locale,
      background,
      foreground,
      shadows,
      fontFeatures,
    );
  }

  /// Merges this text style with [other] and returns the new text style.
  ///
  /// The values in this text style are used unless [other] specifically
  /// overrides it.
  CkTextStyle mergeWith(CkTextStyle other) {
    return CkTextStyle(
      color: other.color ?? color,
      decoration: other.decoration ?? decoration,
      decorationColor: other.decorationColor ?? decorationColor,
      decorationStyle: other.decorationStyle ?? decorationStyle,
      decorationThickness: other.decorationThickness ?? decorationThickness,
      fontWeight: other.fontWeight ?? fontWeight,
      fontStyle: other.fontStyle ?? fontStyle,
      textBaseline: other.textBaseline ?? textBaseline,
      fontFamily: other.fontFamily ?? fontFamily,
      fontFamilyFallback: other.fontFamilyFallback ?? fontFamilyFallback,
      fontSize: other.fontSize ?? fontSize,
      letterSpacing: other.letterSpacing ?? letterSpacing,
      wordSpacing: other.wordSpacing ?? wordSpacing,
      height: other.height ?? height,
      locale: other.locale ?? locale,
      background: other.background ?? background,
      foreground: other.foreground ?? foreground,
      shadows: other.shadows ?? shadows,
      fontFeatures: other.fontFeatures ?? fontFeatures,
    );
  }

  CkTextStyle._(
    this.skTextStyle,
    this.color,
    this.decoration,
    this.decorationColor,
    this.decorationStyle,
    this.decorationThickness,
    this.fontWeight,
    this.fontStyle,
    this.textBaseline,
    this.fontFamily,
    this.fontFamilyFallback,
    this.fontSize,
    this.letterSpacing,
    this.wordSpacing,
    this.height,
    this.locale,
    this.background,
    this.foreground,
    this.shadows,
    this.fontFeatures,
  );
}

SkFontStyle toSkFontStyle(ui.FontWeight? fontWeight, ui.FontStyle? fontStyle) {
  final style = SkFontStyle();
  if (fontWeight != null) {
    style.weight = toSkFontWeight(fontWeight);
  }
  if (fontStyle != null) {
    style.slant = toSkFontSlant(fontStyle);
  }
  return style;
}

class CkParagraph extends ManagedSkiaObject<SkParagraph>
    implements ui.Paragraph {
  CkParagraph(
      this._initialParagraph, this._paragraphStyle, this._paragraphCommands);

  /// The result of calling `build()` on the JS CkParagraphBuilder.
  ///
  /// This may be invalidated later.
  final SkParagraph _initialParagraph;

  /// The paragraph style used to build this paragraph.
  ///
  /// This is used to resurrect the paragraph if the initial paragraph
  /// is deleted.
  final CkParagraphStyle _paragraphStyle;

  /// The paragraph builder commands used to build this paragraph.
  ///
  /// This is used to resurrect the paragraph if the initial paragraph
  /// is deleted.
  final List<_ParagraphCommand> _paragraphCommands;

  /// The constraints from the last time we layed the paragraph out.
  ///
  /// This is used to resurrect the paragraph if the initial paragraph
  /// is deleted.
  ui.ParagraphConstraints? _lastLayoutConstraints;

  @override
  SkParagraph createDefault() => _initialParagraph;

  @override
  SkParagraph resurrect() {
    final builder = CkParagraphBuilder(_paragraphStyle);
    for (_ParagraphCommand command in _paragraphCommands) {
      switch (command.type) {
        case _ParagraphCommandType.addText:
          builder.addText(command.text!);
          break;
        case _ParagraphCommandType.pop:
          builder.pop();
          break;
        case _ParagraphCommandType.pushStyle:
          builder.pushStyle(command.style!);
          break;
        case _ParagraphCommandType.addPlaceholder:
          builder._addPlaceholder(command.placeholderStyle!);
          break;
      }
    }

    final SkParagraph result = builder._buildCkParagraph();
    if (_lastLayoutConstraints != null) {
      // We need to set the Skia object early so layout works.
      rawSkiaObject = result;
      this.layout(_lastLayoutConstraints!);
    }
    return result;
  }

  @override
  void delete() {
    rawSkiaObject?.delete();
  }

  @override
  bool get isResurrectionExpensive => true;

  @override
  double get alphabeticBaseline => skiaObject.getAlphabeticBaseline();

  @override
  bool get didExceedMaxLines => skiaObject.didExceedMaxLines();

  @override
  double get height => skiaObject.getHeight();

  @override
  double get ideographicBaseline => skiaObject.getIdeographicBaseline();

  @override
  double get longestLine => skiaObject.getLongestLine();

  @override
  double get maxIntrinsicWidth => skiaObject.getMaxIntrinsicWidth();

  @override
  double get minIntrinsicWidth => skiaObject.getMinIntrinsicWidth();

  @override
  double get width => skiaObject.getMaxWidth();

  @override
  List<ui.TextBox> getBoxesForPlaceholders() {
    List<List<double>> skRects = skiaObject.getRectsForPlaceholders();
    return skRectsToTextBoxes(skRects);
  }

  @override
  List<ui.TextBox> getBoxesForRange(
    int start,
    int end, {
    ui.BoxHeightStyle boxHeightStyle: ui.BoxHeightStyle.tight,
    ui.BoxWidthStyle boxWidthStyle: ui.BoxWidthStyle.tight,
  }) {
    if (start < 0 || end < 0) {
      return const <ui.TextBox>[];
    }

    List<List<double>> skRects = skiaObject.getRectsForRange(
      start,
      end,
      toSkRectHeightStyle(boxHeightStyle),
      toSkRectWidthStyle(boxWidthStyle),
    );

    return skRectsToTextBoxes(skRects);
  }

  List<ui.TextBox> skRectsToTextBoxes(List<List<double>> skRects) {
    List<ui.TextBox> result = <ui.TextBox>[];

    for (int i = 0; i < skRects.length; i++) {
      final List<double> rect = skRects[i];
      result.add(ui.TextBox.fromLTRBD(
          rect[0],
          rect[1],
          rect[2],
          rect[3],
        _paragraphStyle._textDirection!,
      ));
    }

    return result;
  }

  @override
  ui.TextPosition getPositionForOffset(ui.Offset offset) {
    final SkTextPosition positionWithAffinity =
        skiaObject.getGlyphPositionAtCoordinate(
      offset.dx,
      offset.dy,
    );
    return fromPositionWithAffinity(positionWithAffinity);
  }

  @override
  ui.TextRange getWordBoundary(ui.TextPosition position) {
    final SkTextRange skRange = skiaObject.getWordBoundary(position.offset);
    return ui.TextRange(start: skRange.start, end: skRange.end);
  }

  @override
  void layout(ui.ParagraphConstraints constraints) {
    assert(constraints.width != null); // ignore: unnecessary_null_comparison
    _lastLayoutConstraints = constraints;

    // Infinite width breaks layout, just use a very large number instead.
    // TODO(het): Remove this once https://bugs.chromium.org/p/skia/issues/detail?id=9874
    //            is fixed.
    double width;
    const double largeFiniteWidth = 1000000;
    if (constraints.width.isInfinite) {
      width = largeFiniteWidth;
    } else {
      width = constraints.width;
    }
    // TODO(het): CanvasKit throws an exception when laid out with
    // a font that wasn't registered.
    try {
      skiaObject.layout(width);
    } catch (e) {
      html.window.console.warn('CanvasKit threw an exception while laying '
          'out the paragraph. The font was "${_paragraphStyle._fontFamily}". '
          'Exception:\n$e');
      rethrow;
    }
  }

  @override
  ui.TextRange getLineBoundary(ui.TextPosition position) {
    // TODO(hterkelsen): Implement this when it's added to CanvasKit
    throw UnimplementedError('getLineBoundary');
  }

  @override
  List<ui.LineMetrics> computeLineMetrics() {
    // TODO(hterkelsen): Implement this when it's added to CanvasKit
    throw UnimplementedError('computeLineMetrics');
  }
}

class CkParagraphBuilder implements ui.ParagraphBuilder {
  final SkParagraphBuilder _paragraphBuilder;
  final CkParagraphStyle _style;
  final List<_ParagraphCommand> _commands;
  int _placeholderCount;
  final List<double> _placeholderScales;
  final List<CkTextStyle> _styleStack;

  CkParagraphBuilder(ui.ParagraphStyle style)
      : _commands = <_ParagraphCommand>[],
        _style = style as CkParagraphStyle,
        _placeholderCount = 0,
        _placeholderScales = <double>[],
        _styleStack = <CkTextStyle>[],
        _paragraphBuilder = canvasKit.ParagraphBuilder.MakeFromFontProvider(
          style.skParagraphStyle,
          skiaFontCollection.fontProvider,
        );

  @override
  void addPlaceholder(
    double width,
    double height,
    ui.PlaceholderAlignment alignment, {
    double scale = 1.0,
    double? baselineOffset,
    ui.TextBaseline? baseline,
  }) {
    // Require a baseline to be specified if using a baseline-based alignment.
    assert((alignment == ui.PlaceholderAlignment.aboveBaseline ||
            alignment == ui.PlaceholderAlignment.belowBaseline ||
            alignment == ui.PlaceholderAlignment.baseline)
        ? baseline != null
        : true);

    _placeholderCount++;
    _placeholderScales.add(scale);
    SkPlaceholderStyleProperties placeholderStyle = toSkPlaceholderStyle(
      width * scale,
      height * scale,
      alignment,
      (baselineOffset ?? height) * scale,
      baseline ?? ui.TextBaseline.alphabetic,
    );
    _addPlaceholder(placeholderStyle);
  }

  void _addPlaceholder(SkPlaceholderStyleProperties placeholderStyle) {
    _commands.add(_ParagraphCommand.addPlaceholder(placeholderStyle));
    _paragraphBuilder.addPlaceholder(placeholderStyle);
  }

  static SkPlaceholderStyleProperties toSkPlaceholderStyle(
    double width,
    double height,
    ui.PlaceholderAlignment alignment,
    double baselineOffset,
    ui.TextBaseline baseline,
  ) {
    final properties = SkPlaceholderStyleProperties();
    properties.width = width;
    properties.height = height;
    properties.alignment = toSkPlaceholderAlignment(alignment);
    properties.offset = baselineOffset;
    properties.baseline = toSkTextBaseline(baseline);
    return properties;
  }

  @override
  void addText(String text) {
    _commands.add(_ParagraphCommand.addText(text));
    _paragraphBuilder.addText(text);
  }

  @override
  ui.Paragraph build() {
    final builtParagraph = _buildCkParagraph();
    return CkParagraph(builtParagraph, _style, _commands);
  }

  /// Builds the CkParagraph with the builder and deletes the builder.
  SkParagraph _buildCkParagraph() {
    final SkParagraph result = _paragraphBuilder.build();
    _paragraphBuilder.delete();
    return result;
  }

  @override
  int get placeholderCount => _placeholderCount;

  @override
  List<double> get placeholderScales => _placeholderScales;

  @override
  void pop() {
    _commands.add(const _ParagraphCommand.pop());
    _styleStack.removeLast();
    _paragraphBuilder.pop();
  }

  CkTextStyle _peekStyle() =>
      _styleStack.isEmpty ? _style.getTextStyle() : _styleStack.last;

  @override
  void pushStyle(ui.TextStyle style) {
    final CkTextStyle baseStyle = _peekStyle();
    final CkTextStyle ckStyle = style as CkTextStyle;
    final CkTextStyle skStyle = baseStyle.mergeWith(ckStyle);
    _styleStack.add(skStyle);
    _commands.add(_ParagraphCommand.pushStyle(ckStyle));
    if (skStyle.foreground != null || skStyle.background != null) {
      final SkPaint foreground = skStyle.foreground?.skiaObject ?? SkPaint();
      final SkPaint background = skStyle.background?.skiaObject ?? SkPaint();
      _paragraphBuilder.pushPaintStyle(
          skStyle.skTextStyle, foreground, background);
    } else {
      _paragraphBuilder.pushStyle(skStyle.skTextStyle);
    }
  }
}

class _ParagraphCommand {
  final _ParagraphCommandType type;
  final String? text;
  final CkTextStyle? style;
  final SkPlaceholderStyleProperties? placeholderStyle;

  const _ParagraphCommand._(
    this.type,
    this.text,
    this.style,
    this.placeholderStyle,
  );

  const _ParagraphCommand.addText(String text)
      : this._(_ParagraphCommandType.addText, text, null, null);

  const _ParagraphCommand.pop()
      : this._(_ParagraphCommandType.pop, null, null, null);

  const _ParagraphCommand.pushStyle(CkTextStyle style)
      : this._(_ParagraphCommandType.pushStyle, null, style, null);

  const _ParagraphCommand.addPlaceholder(
      SkPlaceholderStyleProperties placeholderStyle)
      : this._(
            _ParagraphCommandType.addPlaceholder, null, null, placeholderStyle);
}

enum _ParagraphCommandType {
  addText,
  pop,
  pushStyle,
  addPlaceholder,
}
