/*
 * Copyright 2019 The Android Open Source Project
 *
 * 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.
 */

package androidx.compose.ui.text

import androidx.annotation.IntRange
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Canvas
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.Shadow
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.DrawStyle
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.createFontFamilyResolver
import androidx.compose.ui.text.platform.drawMultiParagraph
import androidx.compose.ui.text.style.ResolvedTextDirection
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Density
import androidx.compose.ui.util.fastFlatMap
import androidx.compose.ui.util.fastForEach
import androidx.compose.ui.util.fastMap

/**
 * Lays out and renders multiple paragraphs at once. Unlike [Paragraph], supports multiple
 * [ParagraphStyle]s in a given text.
 *
 * @param intrinsics previously calculated text intrinsics
 * @param constraints how wide and tall the text is allowed to be. [Constraints.maxWidth]
 * will define the width of the MultiParagraph. [Constraints.maxHeight] helps defining the
 * number of lines that fit with ellipsis is true. Minimum components of the [Constraints]
 * object are no-op.
 * @param maxLines the maximum number of lines that the text can have
 * @param ellipsis whether to ellipsize text, applied only when [maxLines] is set
 */
class MultiParagraph(
    val intrinsics: MultiParagraphIntrinsics,
    constraints: Constraints,
    val maxLines: Int = DefaultMaxLines,
    ellipsis: Boolean = false,
) {

    /**
     * Lays out and renders multiple paragraphs at once. Unlike [Paragraph], supports multiple
     * [ParagraphStyle]s in a given text.
     *
     * @param intrinsics previously calculated text intrinsics
     * @param maxLines the maximum number of lines that the text can have
     * @param ellipsis whether to ellipsize text, applied only when [maxLines] is set
     * @param width how wide the text is allowed to be
     */
    @Deprecated(
        "MultiParagraph that takes maximum allowed width is deprecated, pass constraints instead.",
        ReplaceWith(
            "MultiParagraph(intrinsics, Constraints(maxWidth = ceil(width).toInt()), " +
                "maxLines, ellipsis)",
            "kotlin.math.ceil",
            "androidx.compose.ui.unit.Constraints"
        )
    )
    constructor(
        intrinsics: MultiParagraphIntrinsics,
        maxLines: Int = DefaultMaxLines,
        ellipsis: Boolean = false,
        width: Float
    ) : this(
        intrinsics,
        Constraints(maxWidth = width.ceilToInt()),
        maxLines,
        ellipsis
    )

    /**
     *  Lays out a given [annotatedString] with the given constraints. Unlike a [Paragraph],
     *  [MultiParagraph] can handle a text what has multiple paragraph styles.
     *
     * @param annotatedString the text to be laid out
     * @param style the [TextStyle] to be applied to the whole text
     * @param placeholders a list of [Placeholder]s that specify ranges of text which will be
     * skipped during layout and replaced with [Placeholder]. It's required that the range of each
     * [Placeholder] doesn't cross paragraph boundary, otherwise [IllegalArgumentException] is
     * thrown.
     * @param maxLines the maximum number of lines that the text can have
     * @param ellipsis whether to ellipsize text, applied only when [maxLines] is set
     * @param width how wide the text is allowed to be
     * @param density density of the device
     * @param resourceLoader [Font.ResourceLoader] to be used to load the font given in [SpanStyle]s
     *
     * @see Placeholder
     * @throws IllegalArgumentException if [ParagraphStyle.textDirection] is not set, or
     * any of the [placeholders] crosses paragraph boundary.
     */
    @Suppress("DEPRECATION")
    @Deprecated("Font.ResourceLoader is deprecated, use fontFamilyResolver instead",
        replaceWith = ReplaceWith("MultiParagraph(annotatedString, style, " +
            "placeholders, maxLines, ellipsis, width, density, fontFamilyResolver)")
    )
    constructor(
        annotatedString: AnnotatedString,
        style: TextStyle,
        placeholders: List<AnnotatedString.Range<Placeholder>> = listOf(),
        maxLines: Int = Int.MAX_VALUE,
        ellipsis: Boolean = false,
        width: Float,
        density: Density,
        resourceLoader: Font.ResourceLoader
    ) : this(
        intrinsics = MultiParagraphIntrinsics(
            annotatedString = annotatedString,
            style = style,
            placeholders = placeholders,
            density = density,
            fontFamilyResolver = createFontFamilyResolver(resourceLoader)
        ),
        maxLines = maxLines,
        ellipsis = ellipsis,
        constraints = Constraints(maxWidth = width.ceilToInt())
    )

    /**
     *  Lays out a given [annotatedString] with the given constraints. Unlike a [Paragraph],
     *  [MultiParagraph] can handle a text what has multiple paragraph styles.
     *
     * @param annotatedString the text to be laid out
     * @param style the [TextStyle] to be applied to the whole text
     * @param width how wide the text is allowed to be
     * @param density density of the device
     * @param fontFamilyResolver to be used to load the font given in [SpanStyle]s
     * @param placeholders a list of [Placeholder]s that specify ranges of text which will be
     * skipped during layout and replaced with [Placeholder]. It's required that the range of each
     * [Placeholder] doesn't cross paragraph boundary, otherwise [IllegalArgumentException] is
     * thrown.
     * @param maxLines the maximum number of lines that the text can have
     * @param ellipsis whether to ellipsize text, applied only when [maxLines] is set
     *
     * @see Placeholder
     * @throws IllegalArgumentException if [ParagraphStyle.textDirection] is not set, or
     * any of the [placeholders] crosses paragraph boundary.
     */
    @Deprecated(
        "MultiParagraph that takes maximum allowed width is deprecated, pass constraints instead.",
        ReplaceWith(
            "MultiParagraph(annotatedString, style, Constraints(maxWidth = ceil(width).toInt()), " +
                "density, fontFamilyResolver, placeholders, maxLines, ellipsis)",
            "kotlin.math.ceil",
            "androidx.compose.ui.unit.Constraints"
        )
    )
    constructor(
        annotatedString: AnnotatedString,
        style: TextStyle,
        width: Float,
        density: Density,
        fontFamilyResolver: FontFamily.Resolver,
        placeholders: List<AnnotatedString.Range<Placeholder>> = listOf(),
        maxLines: Int = Int.MAX_VALUE,
        ellipsis: Boolean = false
    ) : this(
        intrinsics = MultiParagraphIntrinsics(
            annotatedString = annotatedString,
            style = style,
            placeholders = placeholders,
            density = density,
            fontFamilyResolver = fontFamilyResolver
        ),
        maxLines = maxLines,
        ellipsis = ellipsis,
        constraints = Constraints(maxWidth = width.ceilToInt())
    )

    /**
     *  Lays out a given [annotatedString] with the given constraints. Unlike a [Paragraph],
     *  [MultiParagraph] can handle a text what has multiple paragraph styles.
     *
     * @param annotatedString the text to be laid out
     * @param style the [TextStyle] to be applied to the whole text
     * @param constraints how wide and tall the text is allowed to be. [Constraints.maxWidth]
     * will define the width of the MultiParagraph. [Constraints.maxHeight] helps defining the
     * number of lines that fit with ellipsis is true. Minimum components of the [Constraints]
     * object are no-op.
     * @param density density of the device
     * @param fontFamilyResolver to be used to load the font given in [SpanStyle]s
     * @param placeholders a list of [Placeholder]s that specify ranges of text which will be
     * skipped during layout and replaced with [Placeholder]. It's required that the range of each
     * [Placeholder] doesn't cross paragraph boundary, otherwise [IllegalArgumentException] is
     * thrown.
     * @param maxLines the maximum number of lines that the text can have
     * @param ellipsis whether to ellipsize text, applied only when [maxLines] is set
     *
     * @see Placeholder
     * @throws IllegalArgumentException if [ParagraphStyle.textDirection] is not set, or
     * any of the [placeholders] crosses paragraph boundary.
     */
    constructor(
        annotatedString: AnnotatedString,
        style: TextStyle,
        constraints: Constraints,
        density: Density,
        fontFamilyResolver: FontFamily.Resolver,
        placeholders: List<AnnotatedString.Range<Placeholder>> = listOf(),
        maxLines: Int = Int.MAX_VALUE,
        ellipsis: Boolean = false
    ) : this(
        intrinsics = MultiParagraphIntrinsics(
            annotatedString = annotatedString,
            style = style,
            placeholders = placeholders,
            density = density,
            fontFamilyResolver = fontFamilyResolver
        ),
        maxLines = maxLines,
        ellipsis = ellipsis,
        constraints = constraints
    )

    private val annotatedString get() = intrinsics.annotatedString

    /**
     * The width for text if all soft wrap opportunities were taken.
     */
    val minIntrinsicWidth: Float get() = intrinsics.minIntrinsicWidth

    /**
     * Returns the smallest width beyond which increasing the width never
     * decreases the height.
     */
    val maxIntrinsicWidth: Float get() = intrinsics.maxIntrinsicWidth

    /**
     * True if there is more vertical content, but the text was truncated, either
     * because we reached `maxLines` lines of text or because the `maxLines` was
     * null, `ellipsis` was not null, and one of the lines exceeded the width
     * constraint.
     */
    val didExceedMaxLines: Boolean

    /**
     * The amount of horizontal space this paragraph occupies.
     */
    val width: Float

    /**
     * The amount of vertical space this paragraph occupies.
     *
     * Valid only after [layout] has been called.
     */
    val height: Float

    /**
     * The distance from the top of the paragraph to the alphabetic
     * baseline of the first line, in logical pixels.
     */
    val firstBaseline: Float
        get() {
            return if (paragraphInfoList.isEmpty()) {
                0f
            } else {
                paragraphInfoList[0].paragraph.firstBaseline
            }
        }

    /**
     * The distance from the top of the paragraph to the alphabetic
     * baseline of the first line, in logical pixels.
     */
    val lastBaseline: Float
        get() {
            return if (paragraphInfoList.isEmpty()) {
                0f
            } else {
                with(paragraphInfoList.last()) {
                    paragraph.lastBaseline.toGlobalYPosition()
                }
            }
        }

    /** The total number of lines in the text. */
    val lineCount: Int

    /**
     * The bounding boxes reserved for the input placeholders in this MultiParagraph. Their
     * locations are relative to this MultiParagraph's coordinate. The order of this list
     * corresponds to that of input placeholders.
     * Notice that [Rect] in [placeholderRects] is nullable. When [Rect] is null, it indicates
     * that the corresponding [Placeholder] is ellipsized.
     */
    val placeholderRects: List<Rect?>

    /* This is internal for testing purpose. */
    internal val paragraphInfoList: List<ParagraphInfo>

    init {
        require(constraints.minWidth == 0 && constraints.minHeight == 0) {
            "Setting Constraints.minWidth and Constraints.minHeight is not supported, " +
                "these should be the default zero values instead."
        }

        var currentHeight = 0f
        var currentLineCount = 0
        var didExceedMaxLines = false

        // create sub paragraphs and layouts
        val paragraphInfoList = mutableListOf<ParagraphInfo>()
        val infoList = intrinsics.infoList
        for (index in infoList.indices) {
            val paragraphInfo = infoList[index]
            val paragraph = Paragraph(
                paragraphInfo.intrinsics,
                Constraints(
                    maxWidth = constraints.maxWidth,
                    maxHeight = if (constraints.hasBoundedHeight) {
                        (constraints.maxHeight - currentHeight.ceilToInt()).coerceAtLeast(0)
                    } else {
                        constraints.maxHeight
                    }
                ),
                maxLines - currentLineCount,
                ellipsis,
            )

            val paragraphTop = currentHeight
            val paragraphBottom = currentHeight + paragraph.height
            currentHeight = paragraphBottom

            val startLineIndex = currentLineCount
            val endLineIndex = startLineIndex + paragraph.lineCount
            currentLineCount = endLineIndex

            paragraphInfoList.add(
                ParagraphInfo(
                    paragraph = paragraph,
                    startIndex = paragraphInfo.startIndex,
                    endIndex = paragraphInfo.endIndex,
                    startLineIndex = startLineIndex,
                    endLineIndex = endLineIndex,
                    top = paragraphTop,
                    bottom = paragraphBottom
                )
            )

            if (paragraph.didExceedMaxLines ||
                (endLineIndex == maxLines && index != intrinsics.infoList.lastIndex)
            ) {
                didExceedMaxLines = true
                break
            }
        }

        this.height = currentHeight
        this.lineCount = currentLineCount
        this.didExceedMaxLines = didExceedMaxLines
        this.paragraphInfoList = paragraphInfoList
        this.width = constraints.maxWidth.toFloat()
        this.placeholderRects = paragraphInfoList.fastFlatMap { paragraphInfo ->
            with(paragraphInfo) {
                paragraph.placeholderRects.fastMap { it?.toGlobal() }
            }
        }.let {
            // When paragraphs get ellipsized, the size of this list will be smaller than
            // the input placeholders. In this case, fill this list with null so that it has the
            // same size as the input placeholders.
            if (it.size < intrinsics.placeholders.size) {
                it + List(intrinsics.placeholders.size - it.size) { null }
            } else {
                it
            }
        }
    }

    /** Paint the paragraphs to canvas. */
    @Deprecated(
        "Use the new paint function that takes canvas as the only required parameter.",
        level = DeprecationLevel.HIDDEN
    )
    fun paint(
        canvas: Canvas,
        color: Color = Color.Unspecified,
        shadow: Shadow? = null,
        decoration: TextDecoration? = null
    ) {
        canvas.save()
        paragraphInfoList.fastForEach {
            it.paragraph.paint(canvas, color, shadow, decoration)
            canvas.translate(0f, it.paragraph.height)
        }
        canvas.restore()
    }

    /** Paint the paragraphs to canvas. */
    fun paint(
        canvas: Canvas,
        color: Color = Color.Unspecified,
        shadow: Shadow? = null,
        decoration: TextDecoration? = null,
        drawStyle: DrawStyle? = null,
        blendMode: BlendMode = DrawScope.DefaultBlendMode
    ) {
        canvas.save()
        paragraphInfoList.fastForEach {
            it.paragraph.paint(canvas, color, shadow, decoration, drawStyle, blendMode)
            canvas.translate(0f, it.paragraph.height)
        }
        canvas.restore()
    }

    /** Paint the paragraphs to canvas. */
    fun paint(
        canvas: Canvas,
        brush: Brush,
        alpha: Float = Float.NaN,
        shadow: Shadow? = null,
        decoration: TextDecoration? = null,
        drawStyle: DrawStyle? = null,
        blendMode: BlendMode = DrawScope.DefaultBlendMode
    ) {
        drawMultiParagraph(canvas, brush, alpha, shadow, decoration, drawStyle, blendMode)
    }

    /** Returns path that enclose the given text range. */
    fun getPathForRange(start: Int, end: Int): Path {
        require(start in 0..end && end <= annotatedString.text.length) {
            "Start($start) or End($end) is out of range [0..${annotatedString.text.length})," +
                " or start > end!"
        }

        if (start == end) return Path()

        val path = Path()
        findParagraphsByRange(paragraphInfoList, TextRange(start, end)) { paragraphInfo ->
            with(paragraphInfo) {
                path.addPath(
                    path = paragraph.getPathForRange(
                        start = start.toLocalIndex(),
                        end = end.toLocalIndex()
                    ).toGlobal()
                )
            }
        }

        return path
    }

    /**
     * Returns line number closest to the given graphical vertical position.
     * If you ask for a vertical position before 0, you get 0; if you ask for a vertical position
     * beyond the last line, you get the last line.
     */
    fun getLineForVerticalPosition(vertical: Float): Int {
        val paragraphIndex = findParagraphByY(paragraphInfoList, vertical)
        return with(paragraphInfoList[paragraphIndex]) {
            if (length == 0) {
                startLineIndex
            } else {
                paragraph.getLineForVerticalPosition(
                    vertical.toLocalYPosition()
                ).toGlobalLineIndex()
            }
        }
    }

    /** Returns the character offset closest to the given graphical position. */
    fun getOffsetForPosition(position: Offset): Int {
        val paragraphIndex = findParagraphByY(paragraphInfoList, position.y)
        return with(paragraphInfoList[paragraphIndex]) {
            if (length == 0) {
                startIndex
            } else {
                paragraph.getOffsetForPosition(position.toLocal()).toGlobalIndex()
            }
        }
    }

    /**
     * Find the range of text which is inside the specified [rect].
     * This method will break text into small text segments based on the given [granularity] such as
     * character or word. It also support different [inclusionStrategy], which determines when a
     * small text segments is considered as inside the [rect].
     * Note that the word/character breaking is both operating system and language dependent.
     * In the certain cases, the text may be break into smaller segments than the specified the
     * [granularity].
     * If a text segment spans multiple lines or multiple directional runs (e.g. a hyphenated word),
     * the text segment is divided into pieces at the line and run breaks, then the text segment is
     * considered to be inside the area if any of its pieces are inside the area.
     *
     * @param rect the rectangle area in which the text range will be found.
     * @param granularity the granularity of the text, it controls how text is segmented.
     * @param inclusionStrategy the strategy that determines whether a range of text's bounds is
     * inside the given [rect] or not.
     * @return the [TextRange] that is inside the given [rect], or [TextRange.Zero] if no text is
     * found.
     */
    fun getRangeForRect(
        rect: Rect,
        granularity: TextGranularity,
        inclusionStrategy: TextInclusionStrategy
    ): TextRange {
        var firstParagraph = findParagraphByY(paragraphInfoList, rect.top)
        // The first paragraph contains the entire rect, return early in this case.
        if (paragraphInfoList[firstParagraph].bottom >= rect.bottom ||
            firstParagraph == paragraphInfoList.lastIndex) {
            return with(paragraphInfoList[firstParagraph]) {
                paragraph.getRangeForRect(
                    rect.toLocal(),
                    granularity,
                    inclusionStrategy
                ).toGlobal()
            }
        }

        var lastParagraph = findParagraphByY(paragraphInfoList, rect.bottom)

        var startRange: TextRange = TextRange.Zero
        while (startRange == TextRange.Zero && firstParagraph <= lastParagraph) {
            startRange = with(paragraphInfoList[firstParagraph]) {
                paragraph.getRangeForRect(
                    rect.toLocal(),
                    granularity,
                    inclusionStrategy
                ).toGlobal()
            }
            ++firstParagraph
        }

        if (startRange == TextRange.Zero) {
            return TextRange.Zero
        }

        var endRange: TextRange = TextRange.Zero
        while (endRange == TextRange.Zero && firstParagraph <= lastParagraph) {
            endRange = with(paragraphInfoList[lastParagraph]) {
                paragraph.getRangeForRect(
                    rect.toLocal(),
                    granularity,
                    inclusionStrategy
                ).toGlobal()
            }
            --lastParagraph
        }

        if (endRange == TextRange.Zero) return startRange
        return TextRange(startRange.start, endRange.end)
    }

    /**
     * Returns the bounding box as Rect of the character for given character offset. Rect
     * includes the top, bottom, left and right of a character.
     */
    fun getBoundingBox(offset: Int): Rect {
        requireIndexInRange(offset)

        val paragraphIndex = findParagraphByIndex(paragraphInfoList, offset)
        return with(paragraphInfoList[paragraphIndex]) {
            paragraph.getBoundingBox(offset.toLocalIndex()).toGlobal()
        }
    }

    /**
     * Fills the bounding boxes for characters provided in the [range] into [array]. The array is
     * filled starting from [arrayStart] (inclusive). The coordinates are in local text layout
     * coordinates.
     *
     * The returned information consists of left/right of a character; line top and bottom for the
     * same character.
     *
     * For the grapheme consists of multiple code points, e.g. ligatures, combining marks, the first
     * character has the total width and the remaining are returned as zero-width.
     *
     * The array divided into segments of four where each index in that segment represents left,
     * top, right, bottom of the character.
     *
     * The size of the provided [array] should be greater or equal than the four times * [TextRange]
     * length.
     *
     * The final order of characters in the [array] is from [TextRange.min] to [TextRange.max].
     *
     * @param range the [TextRange] representing the start and end indices in the [Paragraph].
     * @param array the array to fill in the values. The array divided into segments of four where
     * each index in that segment represents left, top, right, bottom of the character.
     * @param arrayStart the inclusive start index in the array where the function will start
     * filling in the values from
     */
    fun fillBoundingBoxes(
        range: TextRange,
        array: FloatArray,
        @IntRange(from = 0) arrayStart: Int
    ): FloatArray {
        requireIndexInRange(range.min)
        requireIndexInRangeInclusiveEnd(range.max)

        var currentArrayStart = arrayStart
        var currentHeight = 0f
        findParagraphsByRange(paragraphInfoList, range) { paragraphInfo ->
            with(paragraphInfo) {
                val paragraphStart = if (startIndex > range.min) startIndex else range.min
                val paragraphEnd = if (endIndex < range.max) endIndex else range.max
                val finalRange = TextRange(
                    paragraphStart.toLocalIndex(),
                    paragraphEnd.toLocalIndex()
                )
                paragraph.fillBoundingBoxes(finalRange, array, currentArrayStart)
                val currentArrayEnd = currentArrayStart + finalRange.length * 4
                var arrayIndex = currentArrayStart
                while (arrayIndex < currentArrayEnd) {
                    // update top and bottom
                    array[arrayIndex + 1] += currentHeight
                    array[arrayIndex + 3] += currentHeight
                    arrayIndex += 4
                }
                currentArrayStart = currentArrayEnd
                currentHeight += paragraphInfo.paragraph.height
            }
        }

        return array
    }

    /**
     * Compute the horizontal position where a newly inserted character at [offset] would be.
     *
     * If the inserted character at [offset] is within a LTR/RTL run, the returned position will be
     * the left(right) edge of the character.
     * ```
     * For example:
     *     Paragraph's direction is LTR.
     *     Text in logic order:               L0 L1 L2 R3 R4 R5
     *     Text in visual order:              L0 L1 L2 R5 R4 R3
     *         position of the offset(2):          |
     *         position of the offset(4):                   |
     *```
     * However, when the [offset] is at the BiDi transition offset, there will be two possible
     * visual positions, which depends on the direction of the inserted character.
     * ```
     * For example:
     *     Paragraph's direction is LTR.
     *     Text in logic order:               L0 L1 L2 R3 R4 R5
     *     Text in visual order:              L0 L1 L2 R5 R4 R3
     *         position of the offset(3):             |           (The inserted character is LTR)
     *                                                         |  (The inserted character is RTL)
     *```
     * In this case, [usePrimaryDirection] will be used to resolve the ambiguity. If true, the
     * inserted character's direction is assumed to be the same as Paragraph's direction.
     * Otherwise, the inserted character's direction is assumed to be the opposite of the
     * Paragraph's direction.
     * ```
     * For example:
     *     Paragraph's direction is LTR.
     *     Text in logic order:               L0 L1 L2 R3 R4 R5
     *     Text in visual order:              L0 L1 L2 R5 R4 R3
     *         position of the offset(3):             |           (usePrimaryDirection is true)
     *                                                         |  (usePrimaryDirection is false)
     *```
     * This method is useful to compute cursor position.
     *
     * @param offset the offset of the character, in the range of [0, length].
     * @param usePrimaryDirection whether the paragraph direction is respected when [offset]
     * points to a BiDi transition point.
     * @return a float number representing the horizontal position in the unit of pixel.
     */
    fun getHorizontalPosition(offset: Int, usePrimaryDirection: Boolean): Float {
        requireIndexInRangeInclusiveEnd(offset)

        val paragraphIndex = if (offset == annotatedString.length) {
            paragraphInfoList.lastIndex
        } else {
            findParagraphByIndex(paragraphInfoList, offset)
        }

        return with(paragraphInfoList[paragraphIndex]) {
            paragraph.getHorizontalPosition(offset.toLocalIndex(), usePrimaryDirection)
        }
    }

    /**
     * Get the text direction of the paragraph containing the given offset.
     */
    fun getParagraphDirection(offset: Int): ResolvedTextDirection {
        requireIndexInRangeInclusiveEnd(offset)

        val paragraphIndex = if (offset == annotatedString.length) {
            paragraphInfoList.lastIndex
        } else {
            findParagraphByIndex(paragraphInfoList, offset)
        }

        return with(paragraphInfoList[paragraphIndex]) {
            paragraph.getParagraphDirection(offset.toLocalIndex())
        }
    }

    /**
     * Get the text direction of the character at the given offset.
     */
    fun getBidiRunDirection(offset: Int): ResolvedTextDirection {
        requireIndexInRangeInclusiveEnd(offset)

        val paragraphIndex = if (offset == annotatedString.length) {
            paragraphInfoList.lastIndex
        } else {
            findParagraphByIndex(paragraphInfoList, offset)
        }

        return with(paragraphInfoList[paragraphIndex]) {
            paragraph.getBidiRunDirection(offset.toLocalIndex())
        }
    }

    /**
     * Returns the TextRange of the word at the given character offset. Characters not
     * part of a word, such as spaces, symbols, and punctuation, have word breaks
     * on both sides. In such cases, this method will return TextRange(offset, offset+1).
     * Word boundaries are defined more precisely in Unicode Standard Annex #29
     * http://www.unicode.org/reports/tr29/#Word_Boundaries
     */
    fun getWordBoundary(offset: Int): TextRange {
        requireIndexInRangeInclusiveEnd(offset)

        val paragraphIndex = if (offset == annotatedString.length) {
            paragraphInfoList.lastIndex
        } else {
            findParagraphByIndex(paragraphInfoList, offset)
        }

        return with(paragraphInfoList[paragraphIndex]) {
            paragraph.getWordBoundary(offset.toLocalIndex()).toGlobal(treatZeroAsNull = false)
        }
    }

    /** Returns rectangle of the cursor area. */
    fun getCursorRect(offset: Int): Rect {
        requireIndexInRangeInclusiveEnd(offset)

        val paragraphIndex = if (offset == annotatedString.length) {
            paragraphInfoList.lastIndex
        } else {
            findParagraphByIndex(paragraphInfoList, offset)
        }

        return with(paragraphInfoList[paragraphIndex]) {
            paragraph.getCursorRect(offset.toLocalIndex()).toGlobal()
        }
    }

    /**
     * Returns the line number on which the specified text offset appears.
     * If you ask for a position before 0, you get 0; if you ask for a position
     * beyond the end of the text, you get the last line.
     */
    fun getLineForOffset(offset: Int): Int {
        val paragraphIndex = if (offset >= annotatedString.length) {
            paragraphInfoList.lastIndex
        } else if (offset < 0) {
            0
        } else {
            findParagraphByIndex(paragraphInfoList, offset)
        }
        return with(paragraphInfoList[paragraphIndex]) {
            paragraph.getLineForOffset(offset.toLocalIndex()).toGlobalLineIndex()
        }
    }

    /** Returns the left x Coordinate of the given line. */
    fun getLineLeft(lineIndex: Int): Float {
        requireLineIndexInRange(lineIndex)

        val paragraphIndex = findParagraphByLineIndex(paragraphInfoList, lineIndex)

        return with(paragraphInfoList[paragraphIndex]) {
            paragraph.getLineLeft(lineIndex.toLocalLineIndex())
        }
    }

    /** Returns the right x Coordinate of the given line. */
    fun getLineRight(lineIndex: Int): Float {
        requireLineIndexInRange(lineIndex)

        val paragraphIndex = findParagraphByLineIndex(paragraphInfoList, lineIndex)

        return with(paragraphInfoList[paragraphIndex]) {
            paragraph.getLineRight(lineIndex.toLocalLineIndex())
        }
    }

    /** Returns the top y coordinate of the given line. */
    fun getLineTop(lineIndex: Int): Float {
        requireLineIndexInRange(lineIndex)

        val paragraphIndex = findParagraphByLineIndex(paragraphInfoList, lineIndex)

        return with(paragraphInfoList[paragraphIndex]) {
            paragraph.getLineTop(lineIndex.toLocalLineIndex()).toGlobalYPosition()
        }
    }

    /**
     * Returns the distance from the top of the [MultiParagraph] to the alphabetic
     * baseline of the given line.
     */
    fun getLineBaseline(lineIndex: Int): Float {
        requireLineIndexInRange(lineIndex)

        val paragraphIndex = findParagraphByLineIndex(paragraphInfoList, lineIndex)

        return with(paragraphInfoList[paragraphIndex]) {
            paragraph.getLineBaseline(lineIndex.toLocalLineIndex()).toGlobalYPosition()
        }
    }

    /** Returns the bottom y coordinate of the given line. */
    fun getLineBottom(lineIndex: Int): Float {
        requireLineIndexInRange(lineIndex)

        val paragraphIndex = findParagraphByLineIndex(paragraphInfoList, lineIndex)

        return with(paragraphInfoList[paragraphIndex]) {
            paragraph.getLineBottom(lineIndex.toLocalLineIndex()).toGlobalYPosition()
        }
    }

    /** Returns the height of the given line. */
    fun getLineHeight(lineIndex: Int): Float {
        requireLineIndexInRange(lineIndex)

        val paragraphIndex = findParagraphByLineIndex(paragraphInfoList, lineIndex)

        return with(paragraphInfoList[paragraphIndex]) {
            paragraph.getLineHeight(lineIndex.toLocalLineIndex())
        }
    }

    /** Returns the width of the given line. */
    fun getLineWidth(lineIndex: Int): Float {
        requireLineIndexInRange(lineIndex)

        val paragraphIndex = findParagraphByLineIndex(paragraphInfoList, lineIndex)

        return with(paragraphInfoList[paragraphIndex]) {
            paragraph.getLineWidth(lineIndex.toLocalLineIndex())
        }
    }

    /** Returns the start offset of the given line, inclusive. */
    fun getLineStart(lineIndex: Int): Int {
        requireLineIndexInRange(lineIndex)

        val paragraphIndex = findParagraphByLineIndex(paragraphInfoList, lineIndex)

        return with(paragraphInfoList[paragraphIndex]) {
            paragraph.getLineStart(lineIndex.toLocalLineIndex()).toGlobalIndex()
        }
    }

    /**
     * Returns the end offset of the given line
     *
     * Characters being ellipsized are treated as invisible characters. So that if visibleEnd is
     * false, it will return line end including the ellipsized characters and vice verse.
     *
     * @param lineIndex the line number
     * @param visibleEnd if true, the returned line end will not count trailing whitespaces or
     * linefeed characters. Otherwise, this function will return the logical line end. By default
     * it's false.
     * @return an exclusive end offset of the line.
     */
    fun getLineEnd(lineIndex: Int, visibleEnd: Boolean = false): Int {
        requireLineIndexInRange(lineIndex)

        val paragraphIndex = findParagraphByLineIndex(paragraphInfoList, lineIndex)

        return with(paragraphInfoList[paragraphIndex]) {
            paragraph.getLineEnd(lineIndex.toLocalLineIndex(), visibleEnd).toGlobalIndex()
        }
    }

    /**
     * Returns true if the given line is ellipsized, otherwise returns false.
     *
     * @param lineIndex a 0 based line index
     * @return true if the given line is ellipsized, otherwise false
     */
    fun isLineEllipsized(lineIndex: Int): Boolean {
        requireLineIndexInRange(lineIndex)
        val paragraphIndex = findParagraphByLineIndex(paragraphInfoList, lineIndex)
        return with(paragraphInfoList[paragraphIndex]) {
            paragraph.isLineEllipsized(lineIndex)
        }
    }

    private fun requireIndexInRange(offset: Int) {
        require(offset in annotatedString.text.indices) {
            "offset($offset) is out of bounds [0, ${annotatedString.length})"
        }
    }

    private fun requireIndexInRangeInclusiveEnd(offset: Int) {
        require(offset in 0..annotatedString.text.length) {
            "offset($offset) is out of bounds [0, ${annotatedString.length}]"
        }
    }

    private fun requireLineIndexInRange(lineIndex: Int) {
        require(lineIndex in 0 until lineCount) {
            "lineIndex($lineIndex) is out of bounds [0, $lineCount)"
        }
    }
}

/**
 * Given an character index of [MultiParagraph.annotatedString], find the corresponding
 * [ParagraphInfo] which covers the provided index.
 *
 * @param paragraphInfoList The list of [ParagraphInfo] containing the information of each
 *  paragraph in the [MultiParagraph].
 * @param index The target index in the [MultiParagraph]. It should be in the range of
 *  [0, text.length)
 * @return The index of the target [ParagraphInfo] in [paragraphInfoList].
 */
internal fun findParagraphByIndex(paragraphInfoList: List<ParagraphInfo>, index: Int): Int {
    return paragraphInfoList.fastBinarySearch { paragraphInfo ->
        when {
            paragraphInfo.startIndex > index -> 1
            paragraphInfo.endIndex <= index -> -1
            else -> 0
        }
    }
}

/**
 * Given the y graphical position relative to this [MultiParagraph], find the index of the
 * corresponding [ParagraphInfo] which occupies the provided position.
 *
 * @param paragraphInfoList The list of [ParagraphInfo] containing the information of each
 *  paragraph in the [MultiParagraph].
 * @param y The y coordinate position relative to the [MultiParagraph].
 * @return The index of the target [ParagraphInfo] in [paragraphInfoList].
 */
internal fun findParagraphByY(paragraphInfoList: List<ParagraphInfo>, y: Float): Int {
    if (y <= 0) return 0
    if (y >= paragraphInfoList.last().bottom) return paragraphInfoList.lastIndex
    return paragraphInfoList.fastBinarySearch { paragraphInfo ->
        when {
            paragraphInfo.top > y -> 1
            paragraphInfo.bottom <= y -> -1
            else -> 0
        }
    }
}

internal fun findParagraphsByRange(
    paragraphInfoList: List<ParagraphInfo>,
    range: TextRange,
    action: (ParagraphInfo) -> Unit
) {
    val paragraphIndex = findParagraphByIndex(paragraphInfoList, range.min)
    for (i in paragraphIndex until paragraphInfoList.size) {
        val paragraph = paragraphInfoList[i]
        if (paragraph.startIndex >= range.max) break
        if (paragraph.startIndex == paragraph.endIndex) continue
        action(paragraph)
    }
}

/**
 * Given an line index in [MultiParagraph], find the corresponding [ParagraphInfo] which
 * covers the provided line index.
 *
 * @param paragraphInfoList The list of [ParagraphInfo] containing the information of each
 *  paragraph in the [MultiParagraph].
 * @param lineIndex The target line index in the [MultiParagraph], it should be in the range of
 *  [0, [MultiParagraph.lineCount])
 * @return The index of the target [ParagraphInfo] in [paragraphInfoList].
 */
internal fun findParagraphByLineIndex(paragraphInfoList: List<ParagraphInfo>, lineIndex: Int): Int {
    return paragraphInfoList.fastBinarySearch { paragraphInfo ->
        when {
            paragraphInfo.startLineIndex > lineIndex -> 1
            paragraphInfo.endLineIndex <= lineIndex -> -1
            else -> 0
        }
    }
}

private inline fun <T> List<T>.fastBinarySearch(comparison: (T) -> Int): Int {
    var low = 0
    var high = size - 1

    while (low <= high) {
        val mid = (low + high).ushr(1) // safe from overflows
        val midVal = get(mid)
        val cmp = comparison(midVal)

        if (cmp < 0)
            low = mid + 1
        else if (cmp > 0)
            high = mid - 1
        else
            return mid // key found
    }
    return -(low + 1) // key not found
}

/**
 * This is a helper data structure to store the information of a single [Paragraph] in an
 * [MultiParagraph]. It's mainly used to convert a global index, lineNumber and [Offset] to the
 * local ones inside the [paragraph], and vice versa.
 *
 * @param paragraph The [Paragraph] object corresponding to this [ParagraphInfo].
 * @param startIndex The start index of this paragraph in the parent [MultiParagraph], inclusive.
 * @param endIndex The end index of this paragraph in the parent [MultiParagraph], exclusive.
 * @param startLineIndex The start line index of this paragraph in the parent [MultiParagraph],
 *  inclusive.
 * @param endLineIndex The end line index of this paragraph in the parent [MultiParagraph],
 *  exclusive.
 * @param top The top position of the [paragraph] relative to the parent [MultiParagraph].
 * @param bottom The bottom position of the [paragraph] relative to the parent [MultiParagraph].
 */
internal data class ParagraphInfo(
    val paragraph: Paragraph,
    val startIndex: Int,
    val endIndex: Int,
    var startLineIndex: Int = -1,
    var endLineIndex: Int = -1,
    var top: Float = -1.0f,
    var bottom: Float = -1.0f
) {

    /**
     * The length of the text in the covered by this paragraph.
     */
    val length
        get() = endIndex - startIndex

    /**
     * Convert an index in the parent [MultiParagraph] to the local index in the [paragraph].
     */
    fun Int.toLocalIndex(): Int {
        return this.coerceIn(startIndex, endIndex) - startIndex
    }

    /**
     * Convert a local index in the [paragraph] to the global index in the parent [MultiParagraph].
     */
    fun Int.toGlobalIndex(): Int {
        return this + startIndex
    }

    /**
     * Convert a line index in the parent [MultiParagraph] to the local line index in the
     * [paragraph].
     *
     */
    fun Int.toLocalLineIndex(): Int {
        return this - startLineIndex
    }

    /**
     * Convert a local line index in the [paragraph] to the global line index in the parent
     * [MultiParagraph].
     */
    fun Int.toGlobalLineIndex(): Int {
        return this + startLineIndex
    }

    /**
     * Convert a local y position relative to [paragraph] to the global y position relative to the
     * parent [MultiParagraph].
     */
    fun Float.toGlobalYPosition(): Float {
        return this + top
    }

    /**
     * Convert a global y position relative to the parent [MultiParagraph] to a local y position
     * relative to [paragraph].
     */
    fun Float.toLocalYPosition(): Float {
        return this - top
    }

    /**
     * Convert a [Offset] relative to the parent [MultiParagraph] to the local [Offset]
     * relative to the [paragraph].
     */
    fun Offset.toLocal(): Offset {
        return Offset(x, y - top)
    }

    /**
     * Convert a [Rect] relative to the [paragraph] to the [Rect] relative to the parent
     * [MultiParagraph].
     */
    fun Rect.toGlobal(): Rect {
        return translate(Offset(0f, this@ParagraphInfo.top))
    }

    /**
     * Convert a [Rect] relative to the parent [MultiParagraph] to the local [Rect] relative to
     * this [paragraph].
     */
    fun Rect.toLocal(): Rect {
        return translate(Offset(0f, -this@ParagraphInfo.top))
    }

    /**
     * Convert a [Path] relative to the [paragraph] to the [Path] relative to the parent
     * [MultiParagraph].
     *
     * Notice that this function changes the input value.
     */
    fun Path.toGlobal(): Path {
        translate(Offset(0f, top))
        return this
    }

    /**
     * Convert a [TextRange] in to the [paragraph] to the [TextRange] in the parent
     * [MultiParagraph].
     * @param treatZeroAsNull whether [TextRange.Zero] is used represents `null`. When it's true,
     * [TextRange.Zero] is not mapped to global index and is returned directly.
     */
    fun TextRange.toGlobal(treatZeroAsNull: Boolean = true): TextRange {
        if (treatZeroAsNull && this == TextRange.Zero) {
            return TextRange.Zero
        }
        return TextRange(start = start.toGlobalIndex(), end = end.toGlobalIndex())
    }
}
