/*
 * 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.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.graphics.Path
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.font.toFontFamily
import androidx.compose.ui.text.platform.SynchronizedObject
import androidx.compose.ui.text.platform.createSynchronizedObject
import androidx.compose.ui.text.platform.synchronized
import androidx.compose.ui.text.style.ResolvedTextDirection
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.LayoutDirection

/**
 * The data class which holds the set of parameters of the text layout computation.
 */
class TextLayoutInput private constructor(
    /**
     * The text used for computing text layout.
     */
    val text: AnnotatedString,

    /**
     * The text layout used for computing this text layout.
     */
    val style: TextStyle,

    /**
     * A list of [Placeholder]s inserted into text layout that reserves space to embed icons or
     * custom emojis. A list of bounding boxes will be returned in
     * [TextLayoutResult.placeholderRects] that corresponds to this input.
     *
     * @see TextLayoutResult.placeholderRects
     * @see MultiParagraph
     * @see MultiParagraphIntrinsics
     */
    val placeholders: List<AnnotatedString.Range<Placeholder>>,

    /**
     * The maxLines param used for computing this text layout.
     */
    val maxLines: Int,

    /**
     * The maxLines param used for computing this text layout.
     */
    val softWrap: Boolean,

    /**
     * The overflow param used for computing this text layout
     */
    val overflow: TextOverflow,

    /**
     * The density param used for computing this text layout.
     */
    val density: Density,

    /**
     * The layout direction used for computing this text layout.
     */
    val layoutDirection: LayoutDirection,

    /**
     * The font resource loader used for computing this text layout.
     *
     * This is no longer used.
     *
     * @see fontFamilyResolver
     */

    @Suppress("DEPRECATION") resourceLoader: Font.ResourceLoader?,

    /**
     * The font resolver used for computing this text layout.
     */
    val fontFamilyResolver: FontFamily.Resolver,

    /**
     * The minimum width provided while calculating this text layout.
     */
    val constraints: Constraints
) {

    private var _developerSuppliedResourceLoader = resourceLoader
    @Deprecated("Replaced with FontFamily.Resolver",
        replaceWith = ReplaceWith("fontFamilyResolver"),
    )
    @Suppress("DEPRECATION")
    val resourceLoader: Font.ResourceLoader
        get() {
            return _developerSuppliedResourceLoader
                ?: DeprecatedBridgeFontResourceLoader.from(fontFamilyResolver)
        }

    @Deprecated(
        "Font.ResourceLoader is replaced with FontFamily.Resolver",
        replaceWith = ReplaceWith("TextLayoutInput(text, style, placeholders, " +
            "maxLines, softWrap, overflow, density, layoutDirection, fontFamilyResolver, " +
            "constraints")
    )
    @Suppress("DEPRECATION")
    constructor(
        text: AnnotatedString,
        style: TextStyle,
        placeholders: List<AnnotatedString.Range<Placeholder>>,
        maxLines: Int,
        softWrap: Boolean,
        overflow: TextOverflow,
        density: Density,
        layoutDirection: LayoutDirection,
        resourceLoader: Font.ResourceLoader,
        constraints: Constraints
    ) : this(
        text,
        style,
        placeholders,
        maxLines,
        softWrap,
        overflow,
        density,
        layoutDirection,
        resourceLoader,
        createFontFamilyResolver(resourceLoader),
        constraints
    )

    constructor(
        text: AnnotatedString,
        style: TextStyle,
        placeholders: List<AnnotatedString.Range<Placeholder>>,
        maxLines: Int,
        softWrap: Boolean,
        overflow: TextOverflow,
        density: Density,
        layoutDirection: LayoutDirection,
        fontFamilyResolver: FontFamily.Resolver,
        constraints: Constraints
    ) : this(
        text,
        style,
        placeholders,
        maxLines,
        softWrap,
        overflow,
        density,
        layoutDirection,
        @Suppress("DEPRECATION") null,
        fontFamilyResolver,
        constraints
    )

    @Deprecated("Font.ResourceLoader is deprecated",
        replaceWith = ReplaceWith("TextLayoutInput(text, style, placeholders," +
            " maxLines, softWrap, overFlow, density, layoutDirection, fontFamilyResolver, " +
            "constraints)")
    )
    // Unfortunately, there's no way to deprecate and add a parameter to a copy chain such that the
    // resolution is valid.
    //
    // However, as this was never intended to be a public function we will not replace it. There is
    // no use case for calling this method directly.
    fun copy(
        text: AnnotatedString = this.text,
        style: TextStyle = this.style,
        placeholders: List<AnnotatedString.Range<Placeholder>> = this.placeholders,
        maxLines: Int = this.maxLines,
        softWrap: Boolean = this.softWrap,
        overflow: TextOverflow = this.overflow,
        density: Density = this.density,
        layoutDirection: LayoutDirection = this.layoutDirection,
        @Suppress("DEPRECATION") resourceLoader: Font.ResourceLoader = this.resourceLoader,
        constraints: Constraints = this.constraints
    ): TextLayoutInput {
        return TextLayoutInput(
            text = text,
            style = style,
            placeholders = placeholders,
            maxLines = maxLines,
            softWrap = softWrap,
            overflow = overflow,
            density = density,
            layoutDirection = layoutDirection,
            resourceLoader = resourceLoader,
            fontFamilyResolver = fontFamilyResolver,
            constraints = constraints
        )
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other !is TextLayoutInput) return false

        if (text != other.text) return false
        if (style != other.style) return false
        if (placeholders != other.placeholders) return false
        if (maxLines != other.maxLines) return false
        if (softWrap != other.softWrap) return false
        if (overflow != other.overflow) return false
        if (density != other.density) return false
        if (layoutDirection != other.layoutDirection) return false
        if (fontFamilyResolver != other.fontFamilyResolver) return false
        if (constraints != other.constraints) return false

        return true
    }

    override fun hashCode(): Int {
        var result = text.hashCode()
        result = 31 * result + style.hashCode()
        result = 31 * result + placeholders.hashCode()
        result = 31 * result + maxLines
        result = 31 * result + softWrap.hashCode()
        result = 31 * result + overflow.hashCode()
        result = 31 * result + density.hashCode()
        result = 31 * result + layoutDirection.hashCode()
        result = 31 * result + fontFamilyResolver.hashCode()
        result = 31 * result + constraints.hashCode()
        return result
    }

    override fun toString(): String {
        return "TextLayoutInput(" +
            "text=$text, " +
            "style=$style, " +
            "placeholders=$placeholders, " +
            "maxLines=$maxLines, " +
            "softWrap=$softWrap, " +
            "overflow=$overflow, " +
            "density=$density, " +
            "layoutDirection=$layoutDirection, " +
            "fontFamilyResolver=$fontFamilyResolver, " +
            "constraints=$constraints" +
            ")"
    }
}

@Suppress("DEPRECATION")
private class DeprecatedBridgeFontResourceLoader private constructor(
    private val fontFamilyResolver: FontFamily.Resolver
) : Font.ResourceLoader {
    @Deprecated(
        "Replaced by FontFamily.Resolver, this method should not be called",
        ReplaceWith("FontFamily.Resolver.resolve(font, )"),
    )
    override fun load(font: Font): Any {
        return fontFamilyResolver.resolve(
            font.toFontFamily(),
            font.weight,
            font.style
        ).value
    }

    companion object {
        // In normal usage will  be a map of size 1.
        //
        // To fill this map with a large number of entries an app must:
        //
        // 1. Repeatedly change FontFamily.Resolver
        // 2. Call the deprecated method getFontResourceLoader on TextLayoutInput
        //
        // If this map is found to be large in profiling of an app, please modify your code to not
        // call getFontResourceLoader, and evaluate if FontFamily.Resolver is being correctly cached
        // (via e.g. remember)
        var cache = mutableMapOf<FontFamily.Resolver, Font.ResourceLoader>()
        val lock: SynchronizedObject = createSynchronizedObject()
        fun from(fontFamilyResolver: FontFamily.Resolver): Font.ResourceLoader {
            synchronized(lock) {
                // the same resolver to return the same ResourceLoader
                cache[fontFamilyResolver]?.let { return it }

                val deprecatedBridgeFontResourceLoader = DeprecatedBridgeFontResourceLoader(
                    fontFamilyResolver
                )
                cache[fontFamilyResolver] = deprecatedBridgeFontResourceLoader
                return deprecatedBridgeFontResourceLoader
            }
        }
    }
}

/**
 * The data class which holds text layout result.
 */
class TextLayoutResult constructor(
    /**
     * The parameters used for computing this text layout result.
     */
    val layoutInput: TextLayoutInput,

    /**
     * The multi paragraph object.
     *
     * This is the result of the text layout computation.
     */
    val multiParagraph: MultiParagraph,

    /**
     * The amount of space required to paint this text in Int.
     */
    val size: IntSize
) {
    /**
     * The distance from the top to the alphabetic baseline of the first line.
     */
    val firstBaseline: Float = multiParagraph.firstBaseline

    /**
     * The distance from the top to the alphabetic baseline of the last line.
     */
    val lastBaseline: Float = multiParagraph.lastBaseline

    /**
     * Returns true if the text is too tall and couldn't fit with given height.
     */
    val didOverflowHeight: Boolean get() = multiParagraph.didExceedMaxLines ||
        size.height < multiParagraph.height

    /**
     * Returns true if the text is too wide and couldn't fit with given width.
     */
    val didOverflowWidth: Boolean get() = size.width < multiParagraph.width

    /**
     * Returns true if either vertical overflow or horizontal overflow happens.
     */
    val hasVisualOverflow: Boolean get() = didOverflowWidth || didOverflowHeight

    /**
     * Returns a list of bounding boxes that is reserved for [TextLayoutInput.placeholders].
     * Each [Rect] in this list corresponds to the [Placeholder] passed to
     * [TextLayoutInput.placeholders] and it will have the height and width specified in the
     * [Placeholder]. It's guaranteed that [TextLayoutInput.placeholders] and
     * [TextLayoutResult.placeholderRects] will have same length and order.
     *
     * @see TextLayoutInput.placeholders
     * @see Placeholder
     */
    val placeholderRects: List<Rect?> = multiParagraph.placeholderRects

    /**
     * Returns a number of lines of this text layout
     */
    val lineCount: Int get() = multiParagraph.lineCount

    /**
     * Returns the start offset of the given line, inclusive.
     *
     * The start offset represents a position in text before the first character in the given line.
     * For example, `getLineStart(1)` will return 4 for the text below
     * <pre>
     * ┌────┐
     * │abcd│
     * │efg │
     * └────┘
     * </pre>
     *
     * @param lineIndex the line number
     * @return the start offset of the line
     */
    fun getLineStart(lineIndex: Int): Int = multiParagraph.getLineStart(lineIndex)

    /**
     * Returns the end offset of the given line.
     *
     * The end offset represents a position in text after the last character in the given line.
     * For example, `getLineEnd(0)` will return 4 for the text below
     * <pre>
     * ┌────┐
     * │abcd│
     * │efg │
     * └────┘
     * </pre>
     *
     * 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 versa.
     *
     * @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 =
        multiParagraph.getLineEnd(lineIndex, visibleEnd)

    /**
     * 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 = multiParagraph.isLineEllipsized(lineIndex)

    /**
     * Returns the top y coordinate of the given line.
     *
     * @param lineIndex the line number
     * @return the line top y coordinate
     */
    fun getLineTop(lineIndex: Int): Float = multiParagraph.getLineTop(lineIndex)

    /**
     * Returns the distance in pixels from the top of the text layout to the alphabetic baseline of
     * the line at index [lineIndex].
     */
    fun getLineBaseline(lineIndex: Int): Float = multiParagraph.getLineBaseline(lineIndex)

    /**
     * Returns the bottom y coordinate of the given line.
     *
     * @param lineIndex the line number
     * @return the line bottom y coordinate
     */
    fun getLineBottom(lineIndex: Int): Float = multiParagraph.getLineBottom(lineIndex)

    /**
     * Returns the left x coordinate of the given line.
     *
     * @param lineIndex the line number
     * @return the line left x coordinate
     */
    fun getLineLeft(lineIndex: Int): Float = multiParagraph.getLineLeft(lineIndex)

    /**
     * Returns the right x coordinate of the given line.
     *
     * @param lineIndex the line number
     * @return the line right x coordinate
     */
    fun getLineRight(lineIndex: Int): Float = multiParagraph.getLineRight(lineIndex)

    /**
     * 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.
     *
     * @param offset a character offset
     * @return the 0 origin line number.
     */
    fun getLineForOffset(offset: Int): Int = multiParagraph.getLineForOffset(offset)

    /**
     * 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.
     *
     * @param vertical the vertical position
     * @return the 0 origin line number.
     */
    fun getLineForVerticalPosition(vertical: Float): Int =
        multiParagraph.getLineForVerticalPosition(vertical)

    /**
     * Get the horizontal position for the specified text [offset].
     *
     * Returns the relative distance from the text starting offset. For example, if the paragraph
     * direction is Left-to-Right, this function returns positive value as a distance from the
     * left-most edge. If the paragraph direction is Right-to-Left, this function returns negative
     * value as a distance from the right-most edge.
     *
     * [usePrimaryDirection] argument is taken into account only when the offset is in the BiDi
     * directional transition point. [usePrimaryDirection] is true means use the primary
     * direction run's coordinate, and use the secondary direction's run's coordinate if false.
     *
     * @param offset a character offset
     * @param usePrimaryDirection true for using the primary run's coordinate if the given
     * offset is in the BiDi directional transition point.
     * @return the relative distance from the text starting edge.
     * @see MultiParagraph.getHorizontalPosition
     */
    fun getHorizontalPosition(offset: Int, usePrimaryDirection: Boolean): Float =
        multiParagraph.getHorizontalPosition(offset, usePrimaryDirection)

    /**
     * Get the text direction of the paragraph containing the given offset.
     *
     * @param offset a character offset
     * @return the paragraph direction
     */
    fun getParagraphDirection(offset: Int): ResolvedTextDirection =
        multiParagraph.getParagraphDirection(offset)

    /**
     * Get the text direction of the resolved BiDi run that the character at the given offset
     * associated with.
     *
     * @param offset a character offset
     * @return the direction of the BiDi run of the given character offset.
     */
    fun getBidiRunDirection(offset: Int): ResolvedTextDirection =
        multiParagraph.getBidiRunDirection(offset)

    /**
     *  Returns the character offset closest to the given graphical position.
     *
     *  @param position a graphical position in this text layout
     *  @return a character offset that is closest to the given graphical position.
     */
    fun getOffsetForPosition(position: Offset): Int =
        multiParagraph.getOffsetForPosition(position)

    /**
     * Returns the bounding box of the character for given character offset.
     *
     * @param offset a character offset
     * @return a bounding box for the character in pixels.
     */
    fun getBoundingBox(offset: Int): Rect = multiParagraph.getBoundingBox(offset)

    /**
     * Returns the text range 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 a text range that contains the given
     * character offset.
     *
     * Word boundaries are defined more precisely in Unicode Standard Annex #29
     * <http://www.unicode.org/reports/tr29/#Word_Boundaries>.
     */
    fun getWordBoundary(offset: Int): TextRange = multiParagraph.getWordBoundary(offset)

    /**
     * Returns the rectangle of the cursor area
     *
     * @param offset An character offset of the cursor
     * @return a rectangle of cursor region
     */
    fun getCursorRect(offset: Int): Rect = multiParagraph.getCursorRect(offset)

    /**
     * Returns path that enclose the given text range.
     *
     * @param start an inclusive start character offset
     * @param end an exclusive end character offset
     * @return a drawing path
     */
    fun getPathForRange(start: Int, end: Int): Path = multiParagraph.getPathForRange(start, end)

    fun copy(
        layoutInput: TextLayoutInput = this.layoutInput,
        size: IntSize = this.size
    ): TextLayoutResult {
        return TextLayoutResult(
            layoutInput = layoutInput,
            multiParagraph = multiParagraph,
            size = size
        )
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other !is TextLayoutResult) return false

        if (layoutInput != other.layoutInput) return false
        if (multiParagraph != other.multiParagraph) return false
        if (size != other.size) return false
        if (firstBaseline != other.firstBaseline) return false
        if (lastBaseline != other.lastBaseline) return false
        if (placeholderRects != other.placeholderRects) return false

        return true
    }

    override fun hashCode(): Int {
        var result = layoutInput.hashCode()
        result = 31 * result + multiParagraph.hashCode()
        result = 31 * result + size.hashCode()
        result = 31 * result + firstBaseline.hashCode()
        result = 31 * result + lastBaseline.hashCode()
        result = 31 * result + placeholderRects.hashCode()
        return result
    }

    override fun toString(): String {
        return "TextLayoutResult(" +
            "layoutInput=$layoutInput, " +
            "multiParagraph=$multiParagraph, " +
            "size=$size, " +
            "firstBaseline=$firstBaseline, " +
            "lastBaseline=$lastBaseline, " +
            "placeholderRects=$placeholderRects" +
            ")"
    }
}
