// Copyright 2014 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.

import 'dart:ui' as ui show ParagraphBuilder, Locale, StringAttribute, LocaleStringAttribute, SpellOutStringAttribute;

import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/services.dart';

import 'basic_types.dart';
import 'inline_span.dart';
import 'text_painter.dart';
import 'text_style.dart';

/// An immutable span of text.
///
/// A [TextSpan] object can be styled using its [style] property. The style will
/// be applied to the [text] and the [children].
///
/// A [TextSpan] object can just have plain text, or it can have children
/// [TextSpan] objects with their own styles that (possibly only partially)
/// override the [style] of this object. If a [TextSpan] has both [text] and
/// [children], then the [text] is treated as if it was an un-styled [TextSpan]
/// at the start of the [children] list. Leaving the [TextSpan.text] field null
/// results in the [TextSpan] acting as an empty node in the [InlineSpan] tree
/// with a list of children.
///
/// To paint a [TextSpan] on a [Canvas], use a [TextPainter]. To display a text
/// span in a widget, use a [RichText]. For text with a single style, consider
/// using the [Text] widget.
///
/// {@tool snippet}
///
/// The text "Hello world!", in black:
///
/// ```dart
/// const TextSpan(
///   text: 'Hello world!',
///   style: TextStyle(color: Colors.black),
/// )
/// ```
/// {@end-tool}
///
/// _There is some more detailed sample code in the documentation for the
/// [recognizer] property._
///
/// The [TextSpan.text] will be used as the semantics label unless overridden
/// by the [TextSpan.semanticsLabel] property. Any [PlaceholderSpan]s in the
/// [TextSpan.children] list will separate the text before and after it into two
/// semantics nodes.
///
/// See also:
///
///  * [WidgetSpan], a leaf node that represents an embedded inline widget in an
///    [InlineSpan] tree. Specify a widget within the [children] list by
///    wrapping the widget with a [WidgetSpan]. The widget will be laid out
///    inline within the paragraph.
///  * [Text], a widget for showing uniformly-styled text.
///  * [RichText], a widget for finer control of text rendering.
///  * [TextPainter], a class for painting [TextSpan] objects on a [Canvas].
@immutable
class TextSpan extends InlineSpan implements HitTestTarget, MouseTrackerAnnotation {
  /// Creates a [TextSpan] with the given values.
  ///
  /// For the object to be useful, at least one of [text] or
  /// [children] should be set.
  const TextSpan({
    this.text,
    this.children,
    TextStyle? style,
    this.recognizer,
    MouseCursor? mouseCursor,
    this.onEnter,
    this.onExit,
    this.semanticsLabel,
    this.locale,
    this.spellOut,
  }) : mouseCursor = mouseCursor ??
         (recognizer == null ? MouseCursor.defer : SystemMouseCursors.click),
       assert(!(text == null && semanticsLabel != null)),
       super(style: style);

  /// The text contained in this span.
  ///
  /// If both [text] and [children] are non-null, the text will precede the
  /// children.
  ///
  /// This getter does not include the contents of its children.
  final String? text;

  /// Additional spans to include as children.
  ///
  /// If both [text] and [children] are non-null, the text will precede the
  /// children.
  ///
  /// Modifying the list after the [TextSpan] has been created is not supported
  /// and may have unexpected results.
  ///
  /// The list must not contain any nulls.
  final List<InlineSpan>? children;

  /// A gesture recognizer that will receive events that hit this span.
  ///
  /// [InlineSpan] itself does not implement hit testing or event dispatch. The
  /// object that manages the [InlineSpan] painting is also responsible for
  /// dispatching events. In the rendering library, that is the
  /// [RenderParagraph] object, which corresponds to the [RichText] widget in
  /// the widgets layer; these objects do not bubble events in [InlineSpan]s,
  /// so a [recognizer] is only effective for events that directly hit the
  /// [text] of that [InlineSpan], not any of its [children].
  ///
  /// [InlineSpan] also does not manage the lifetime of the gesture recognizer.
  /// The code that owns the [GestureRecognizer] object must call
  /// [GestureRecognizer.dispose] when the [InlineSpan] object is no longer
  /// used.
  ///
  /// {@tool snippet}
  ///
  /// This example shows how to manage the lifetime of a gesture recognizer
  /// provided to an [InlineSpan] object. It defines a `BuzzingText` widget
  /// which uses the [HapticFeedback] class to vibrate the device when the user
  /// long-presses the "find the" span, which is underlined in wavy green. The
  /// hit-testing is handled by the [RichText] widget. It also changes the
  /// hovering mouse cursor to `precise`.
  ///
  /// ```dart
  /// class BuzzingText extends StatefulWidget {
  ///   const BuzzingText({Key? key}) : super(key: key);
  ///
  ///   @override
  ///   State<BuzzingText> createState() => _BuzzingTextState();
  /// }
  ///
  /// class _BuzzingTextState extends State<BuzzingText> {
  ///   late LongPressGestureRecognizer _longPressRecognizer;
  ///
  ///   @override
  ///   void initState() {
  ///     super.initState();
  ///     _longPressRecognizer = LongPressGestureRecognizer()
  ///       ..onLongPress = _handlePress;
  ///   }
  ///
  ///   @override
  ///   void dispose() {
  ///     _longPressRecognizer.dispose();
  ///     super.dispose();
  ///   }
  ///
  ///   void _handlePress() {
  ///     HapticFeedback.vibrate();
  ///   }
  ///
  ///   @override
  ///   Widget build(BuildContext context) {
  ///     return Text.rich(
  ///       TextSpan(
  ///         text: 'Can you ',
  ///         style: const TextStyle(color: Colors.black),
  ///         children: <InlineSpan>[
  ///           TextSpan(
  ///             text: 'find the',
  ///             style: const TextStyle(
  ///               color: Colors.green,
  ///               decoration: TextDecoration.underline,
  ///               decorationStyle: TextDecorationStyle.wavy,
  ///             ),
  ///             recognizer: _longPressRecognizer,
  ///             mouseCursor: SystemMouseCursors.precise,
  ///           ),
  ///           const TextSpan(
  ///             text: ' secret?',
  ///           ),
  ///         ],
  ///       ),
  ///     );
  ///   }
  /// }
  /// ```
  /// {@end-tool}
  final GestureRecognizer? recognizer;

  /// Mouse cursor when the mouse hovers over this span.
  ///
  /// The default value is [SystemMouseCursors.click] if [recognizer] is not
  /// null, or [MouseCursor.defer] otherwise.
  ///
  /// [TextSpan] itself does not implement hit testing or cursor changing.
  /// The object that manages the [TextSpan] painting is responsible
  /// to return the [TextSpan] in its hit test, as well as providing the
  /// correct mouse cursor when the [TextSpan]'s mouse cursor is
  /// [MouseCursor.defer].
  final MouseCursor mouseCursor;

  @override
  final PointerEnterEventListener? onEnter;

  @override
  final PointerExitEventListener? onExit;

  /// Returns the value of [mouseCursor].
  ///
  /// This field, required by [MouseTrackerAnnotation], is hidden publicly to
  /// avoid the confusion as a text cursor.
  @protected
  @override
  MouseCursor get cursor => mouseCursor;

  /// An alternative semantics label for this [TextSpan].
  ///
  /// If present, the semantics of this span will contain this value instead
  /// of the actual text.
  ///
  /// This is useful for replacing abbreviations or shorthands with the full
  /// text value:
  ///
  /// ```dart
  /// TextSpan(text: r'$$', semanticsLabel: 'Double dollars')
  /// ```
  final String? semanticsLabel;

  /// The language of the text in this span and its span children.
  ///
  /// Setting the locale of this text span affects the way that assistive
  /// technologies, such as VoiceOver or TalkBack, pronounce the text.
  ///
  /// If this span contains other text span children, they also inherit the
  /// locale from this span unless explicitly set to different locales.
  final ui.Locale? locale;

  /// Whether the assistive technologies should spell out this text character
  /// by character.
  ///
  /// If the text is 'hello world', setting this to true causes the assistive
  /// technologies, such as VoiceOver or TalkBack, to pronounce
  /// 'h-e-l-l-o-space-w-o-r-l-d' instead of complete words. This is useful for
  /// texts, such as passwords or verification codes.
  ///
  /// If this span contains other text span children, they also inherit the
  /// property from this span unless explicitly set.
  ///
  /// If the property is not set, this text span inherits the spell out setting
  /// from its parent. If this text span does not have a parent or the parent
  /// does not have a spell out setting, this text span does not spell out the
  /// text by default.
  final bool? spellOut;

  @override
  bool get validForMouseTracker => true;

  @override
  void handleEvent(PointerEvent event, HitTestEntry entry) {
    if (event is PointerDownEvent)
      recognizer?.addPointer(event);
  }

  /// Apply the [style], [text], and [children] of this object to the
  /// given [ParagraphBuilder], from which a [Paragraph] can be obtained.
  /// [Paragraph] objects can be drawn on [Canvas] objects.
  ///
  /// Rather than using this directly, it's simpler to use the
  /// [TextPainter] class to paint [TextSpan] objects onto [Canvas]
  /// objects.
  @override
  void build(
    ui.ParagraphBuilder builder, {
    double textScaleFactor = 1.0,
    List<PlaceholderDimensions>? dimensions,
  }) {
    assert(debugAssertIsValid());
    final bool hasStyle = style != null;
    if (hasStyle)
      builder.pushStyle(style!.getTextStyle(textScaleFactor: textScaleFactor));
    if (text != null) {
      try {
        builder.addText(text!);
      } on ArgumentError catch (exception, stack) {
        FlutterError.reportError(FlutterErrorDetails(
          exception: exception,
          stack: stack,
          library: 'painting library',
          context: ErrorDescription('while building a TextSpan'),
        ));
        // Use a Unicode replacement character as a substitute for invalid text.
        builder.addText('\uFFFD');
      }
    }
    if (children != null) {
      for (final InlineSpan child in children!) {
        assert(child != null);
        child.build(
          builder,
          textScaleFactor: textScaleFactor,
          dimensions: dimensions,
        );
      }
    }
    if (hasStyle)
      builder.pop();
  }

  /// Walks this [TextSpan] and its descendants in pre-order and calls [visitor]
  /// for each span that has text.
  ///
  /// When `visitor` returns true, the walk will continue. When `visitor`
  /// returns false, then the walk will end.
  @override
  bool visitChildren(InlineSpanVisitor visitor) {
    if (text != null) {
      if (!visitor(this))
        return false;
    }
    if (children != null) {
      for (final InlineSpan child in children!) {
        if (!child.visitChildren(visitor))
          return false;
      }
    }
    return true;
  }

  /// Returns the text span that contains the given position in the text.
  @override
  InlineSpan? getSpanForPositionVisitor(TextPosition position, Accumulator offset) {
    if (text == null) {
      return null;
    }
    final TextAffinity affinity = position.affinity;
    final int targetOffset = position.offset;
    final int endOffset = offset.value + text!.length;
    if (offset.value == targetOffset && affinity == TextAffinity.downstream ||
        offset.value < targetOffset && targetOffset < endOffset ||
        endOffset == targetOffset && affinity == TextAffinity.upstream) {
      return this;
    }
    offset.increment(text!.length);
    return null;
  }

  @override
  void computeToPlainText(
    StringBuffer buffer, {
    bool includeSemanticsLabels = true,
    bool includePlaceholders = true,
  }) {
    assert(debugAssertIsValid());
    if (semanticsLabel != null && includeSemanticsLabels) {
      buffer.write(semanticsLabel);
    } else if (text != null) {
      buffer.write(text);
    }
    if (children != null) {
      for (final InlineSpan child in children!) {
        child.computeToPlainText(buffer,
          includeSemanticsLabels: includeSemanticsLabels,
          includePlaceholders: includePlaceholders,
        );
      }
    }
  }

  @override
  void computeSemanticsInformation(
    List<InlineSpanSemanticsInformation> collector, {
    ui.Locale? inheritedLocale,
    bool inheritedSpellOut = false,
  }) {
    assert(debugAssertIsValid());
    final ui.Locale? effectiveLocale = locale ?? inheritedLocale;
    final bool effectiveSpellOut = spellOut ?? inheritedSpellOut;

    if (text != null) {
      final int textLength = semanticsLabel?.length ?? text!.length;
      collector.add(InlineSpanSemanticsInformation(
        text!,
        stringAttributes: <ui.StringAttribute>[
          if (effectiveSpellOut && textLength > 0)
            ui.SpellOutStringAttribute(range: TextRange(start: 0, end: textLength)),
          if (effectiveLocale != null && textLength > 0)
            ui.LocaleStringAttribute(locale: effectiveLocale, range: TextRange(start: 0, end: textLength)),
        ],
        semanticsLabel: semanticsLabel,
        recognizer: recognizer,
      ));
    }
    if (children != null) {
      for (final InlineSpan child in children!) {
        if (child is TextSpan) {
          child.computeSemanticsInformation(
            collector,
            inheritedLocale: effectiveLocale,
            inheritedSpellOut: effectiveSpellOut,
          );
        } else {
          child.computeSemanticsInformation(collector);
        }
      }
    }
  }

  @override
  int? codeUnitAtVisitor(int index, Accumulator offset) {
    if (text == null) {
      return null;
    }
    if (index - offset.value < text!.length) {
      return text!.codeUnitAt(index - offset.value);
    }
    offset.increment(text!.length);
    return null;
  }

  /// Populates the `semanticsOffsets` and `semanticsElements` with the appropriate data
  /// to be able to construct a [SemanticsNode].
  ///
  /// If applicable, the beginning and end text offset are added to [semanticsOffsets].
  /// [PlaceholderSpan]s have a text length of 1, which corresponds to the object
  /// replacement character (0xFFFC) that is inserted to represent it.
  ///
  /// Any [GestureRecognizer]s are added to `semanticsElements`. Null is added to
  /// `semanticsElements` for [PlaceholderSpan]s.
  void describeSemantics(Accumulator offset, List<int> semanticsOffsets, List<dynamic> semanticsElements) {
    if (
      recognizer != null &&
      (recognizer is TapGestureRecognizer || recognizer is LongPressGestureRecognizer)
    ) {
      final int length = semanticsLabel?.length ?? text!.length;
      semanticsOffsets.add(offset.value);
      semanticsOffsets.add(offset.value + length);
      semanticsElements.add(recognizer);
    }
    offset.increment(text != null ? text!.length : 0);
  }

  /// In debug mode, throws an exception if the object is not in a valid
  /// configuration. Otherwise, returns true.
  ///
  /// This is intended to be used as follows:
  ///
  /// ```dart
  /// assert(myTextSpan.debugAssertIsValid());
  /// ```
  @override
  bool debugAssertIsValid() {
    assert(() {
      if (children != null) {
        for (final InlineSpan child in children!) {
          if (child == null) {
            throw FlutterError.fromParts(<DiagnosticsNode>[
              ErrorSummary('TextSpan contains a null child.'),
              ErrorDescription(
                'A TextSpan object with a non-null child list should not have any nulls in its child list.',
              ),
              toDiagnosticsNode(
                name: 'The full text in question was',
                style: DiagnosticsTreeStyle.errorProperty,
              ),
            ]);
          }
          assert(child.debugAssertIsValid());
        }
      }
      return true;
    }());
    return super.debugAssertIsValid();
  }

  @override
  RenderComparison compareTo(InlineSpan other) {
    if (identical(this, other))
      return RenderComparison.identical;
    if (other.runtimeType != runtimeType)
      return RenderComparison.layout;
    final TextSpan textSpan = other as TextSpan;
    if (textSpan.text != text ||
        children?.length != textSpan.children?.length ||
        (style == null) != (textSpan.style == null))
      return RenderComparison.layout;
    RenderComparison result = recognizer == textSpan.recognizer ?
      RenderComparison.identical :
      RenderComparison.metadata;
    if (style != null) {
      final RenderComparison candidate = style!.compareTo(textSpan.style!);
      if (candidate.index > result.index)
        result = candidate;
      if (result == RenderComparison.layout)
        return result;
    }
    if (children != null) {
      for (int index = 0; index < children!.length; index += 1) {
        final RenderComparison candidate = children![index].compareTo(textSpan.children![index]);
        if (candidate.index > result.index)
          result = candidate;
        if (result == RenderComparison.layout)
          return result;
      }
    }
    return result;
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other))
      return true;
    if (other.runtimeType != runtimeType)
      return false;
    if (super != other)
      return false;
    return other is TextSpan
        && other.text == text
        && other.recognizer == recognizer
        && other.semanticsLabel == semanticsLabel
        && onEnter == other.onEnter
        && onExit == other.onExit
        && mouseCursor == other.mouseCursor
        && listEquals<InlineSpan>(other.children, children);
  }

  @override
  int get hashCode => hashValues(
    super.hashCode,
    text,
    recognizer,
    semanticsLabel,
    onEnter,
    onExit,
    mouseCursor,
    hashList(children),
  );

  @override
  String toStringShort() => objectRuntimeType(this, 'TextSpan');

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);

    properties.add(
      StringProperty(
        'text',
        text,
        showName: false,
        defaultValue: null,
      ),
    );
    if (style == null && text == null && children == null)
      properties.add(DiagnosticsNode.message('(empty)'));

    properties.add(DiagnosticsProperty<GestureRecognizer>(
      'recognizer', recognizer,
      description: recognizer?.runtimeType.toString(),
      defaultValue: null,
    ));

    properties.add(FlagsSummary<Function?>(
      'callbacks',
      <String, Function?> {
        'enter': onEnter,
        'exit': onExit,
      },
    ));
    properties.add(DiagnosticsProperty<MouseCursor>('mouseCursor', cursor, defaultValue: MouseCursor.defer));

    if (semanticsLabel != null) {
      properties.add(StringProperty('semanticsLabel', semanticsLabel));
    }
  }

  @override
  List<DiagnosticsNode> debugDescribeChildren() {
    if (children == null)
      return const <DiagnosticsNode>[];
    return children!.map<DiagnosticsNode>((InlineSpan child) {
      // `child` has a non-nullable return type, but might be null when running
      // with weak checking, so we need to null check it anyway (and ignore the
      // warning that the null-handling logic is dead code).
      if (child != null) {
        return child.toDiagnosticsNode();
      } else {
        return DiagnosticsNode.message('<null child>');
      }
    }).toList();
  }
}
