/*
 * Copyright (C) 2017 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 android.text;

import android.annotation.IntRange;
import android.annotation.NonNull;
import android.util.IntArray;

import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;

import java.util.ArrayList;

/**
 * A text which has already been measured.
 */
public class MeasuredText implements Spanned {
    private static final char LINE_FEED = '\n';

    // The original text.
    private final @NonNull CharSequence mText;

    // The inclusive start offset of the measuring target.
    private final @IntRange(from = 0) int mStart;

    // The exclusive end offset of the measuring target.
    private final @IntRange(from = 0) int mEnd;

    // The TextPaint used for measurement.
    private final @NonNull TextPaint mPaint;

    // The requested text direction.
    private final @NonNull TextDirectionHeuristic mTextDir;

    // The measured paragraph texts.
    private final @NonNull MeasuredParagraph[] mMeasuredParagraphs;

    // The sorted paragraph end offsets.
    private final @NonNull int[] mParagraphBreakPoints;

    // The break strategy for this measured text.
    private final @Layout.BreakStrategy int mBreakStrategy;

    // The hyphenation frequency for this measured text.
    private final @Layout.HyphenationFrequency int mHyphenationFrequency;

    /**
     * A Builder for MeasuredText
     */
    public static final class Builder {
        // Mandatory parameters.
        private final @NonNull CharSequence mText;
        private final @NonNull TextPaint mPaint;

        // Members to be updated by setters.
        private @IntRange(from = 0) int mStart;
        private @IntRange(from = 0) int mEnd;
        private TextDirectionHeuristic mTextDir = TextDirectionHeuristics.FIRSTSTRONG_LTR;
        private @Layout.BreakStrategy int mBreakStrategy = Layout.BREAK_STRATEGY_HIGH_QUALITY;
        private @Layout.HyphenationFrequency int mHyphenationFrequency =
                Layout.HYPHENATION_FREQUENCY_NORMAL;


        /**
         * Builder constructor
         *
         * @param text The text to be measured.
         * @param paint The paint to be used for drawing.
         */
        public Builder(@NonNull CharSequence text, @NonNull TextPaint paint) {
            Preconditions.checkNotNull(text);
            Preconditions.checkNotNull(paint);

            mText = text;
            mPaint = paint;
            mStart = 0;
            mEnd = text.length();
        }

        /**
         * Set the range of measuring target.
         *
         * @param start The measuring target start offset in the text.
         * @param end The measuring target end offset in the text.
         */
        public @NonNull Builder setRange(@IntRange(from = 0) int start,
                                         @IntRange(from = 0) int end) {
            Preconditions.checkArgumentInRange(start, 0, mText.length(), "start");
            Preconditions.checkArgumentInRange(end, 0, mText.length(), "end");
            Preconditions.checkArgument(start <= end, "The range is reversed.");

            mStart = start;
            mEnd = end;
            return this;
        }

        /**
         * Set the text direction heuristic
         *
         * The default value is {@link TextDirectionHeuristics#FIRSTSTRONG_LTR}.
         *
         * @param textDir The text direction heuristic for resolving bidi behavior.
         * @return this builder, useful for chaining.
         */
        public @NonNull Builder setTextDirection(@NonNull TextDirectionHeuristic textDir) {
            Preconditions.checkNotNull(textDir);
            mTextDir = textDir;
            return this;
        }

        /**
         * Set the break strategy
         *
         * The default value is {@link Layout#BREAK_STRATEGY_HIGH_QUALITY}.
         *
         * @param breakStrategy The break strategy.
         * @return this builder, useful for chaining.
         */
        public @NonNull Builder setBreakStrategy(@Layout.BreakStrategy int breakStrategy) {
            mBreakStrategy = breakStrategy;
            return this;
        }

        /**
         * Set the hyphenation frequency
         *
         * The default value is {@link Layout#HYPHENATION_FREQUENCY_NORMAL}.
         *
         * @param hyphenationFrequency The hyphenation frequency.
         * @return this builder, useful for chaining.
         */
        public @NonNull Builder setHyphenationFrequency(
                @Layout.HyphenationFrequency int hyphenationFrequency) {
            mHyphenationFrequency = hyphenationFrequency;
            return this;
        }

        /**
         * Build the measured text
         *
         * @return the measured text.
         */
        public @NonNull MeasuredText build() {
            return build(true /* build full layout result */);
        }

        /** @hide */
        public @NonNull MeasuredText build(boolean computeLayout) {
            final boolean needHyphenation = mBreakStrategy != Layout.BREAK_STRATEGY_SIMPLE
                    && mHyphenationFrequency != Layout.HYPHENATION_FREQUENCY_NONE;

            final IntArray paragraphEnds = new IntArray();
            final ArrayList<MeasuredParagraph> measuredTexts = new ArrayList<>();

            int paraEnd = 0;
            for (int paraStart = mStart; paraStart < mEnd; paraStart = paraEnd) {
                paraEnd = TextUtils.indexOf(mText, LINE_FEED, paraStart, mEnd);
                if (paraEnd < 0) {
                    // No LINE_FEED(U+000A) character found. Use end of the text as the paragraph
                    // end.
                    paraEnd = mEnd;
                } else {
                    paraEnd++;  // Includes LINE_FEED(U+000A) to the prev paragraph.
                }

                paragraphEnds.add(paraEnd);
                measuredTexts.add(MeasuredParagraph.buildForStaticLayout(
                        mPaint, mText, paraStart, paraEnd, mTextDir, needHyphenation,
                        computeLayout, null /* no recycle */));
            }

            return new MeasuredText(mText, mStart, mEnd, mPaint, mTextDir, mBreakStrategy,
                                    mHyphenationFrequency, measuredTexts.toArray(
                                            new MeasuredParagraph[measuredTexts.size()]),
                                    paragraphEnds.toArray());
        }
    };

    // Use MeasuredText.Builder instead.
    private MeasuredText(@NonNull CharSequence text,
                         @IntRange(from = 0) int start,
                         @IntRange(from = 0) int end,
                         @NonNull TextPaint paint,
                         @NonNull TextDirectionHeuristic textDir,
                         @Layout.BreakStrategy int breakStrategy,
                         @Layout.HyphenationFrequency int frequency,
                         @NonNull MeasuredParagraph[] measuredTexts,
                         @NonNull int[] paragraphBreakPoints) {
        mText = text;
        mStart = start;
        mEnd = end;
        // Copy the paint so that we can keep the reference of typeface in native layout result.
        mPaint = new TextPaint(paint);
        mMeasuredParagraphs = measuredTexts;
        mParagraphBreakPoints = paragraphBreakPoints;
        mTextDir = textDir;
        mBreakStrategy = breakStrategy;
        mHyphenationFrequency = frequency;
    }

    /**
     * Return the underlying text.
     */
    public @NonNull CharSequence getText() {
        return mText;
    }

    /**
     * Returns the inclusive start offset of measured region.
     */
    public @IntRange(from = 0) int getStart() {
        return mStart;
    }

    /**
     * Returns the exclusive end offset of measured region.
     */
    public @IntRange(from = 0) int getEnd() {
        return mEnd;
    }

    /**
     * Returns the text direction associated with char sequence.
     */
    public @NonNull TextDirectionHeuristic getTextDir() {
        return mTextDir;
    }

    /**
     * Returns the paint used to measure this text.
     */
    public @NonNull TextPaint getPaint() {
        return mPaint;
    }

    /**
     * Returns the length of the paragraph of this text.
     */
    public @IntRange(from = 0) int getParagraphCount() {
        return mParagraphBreakPoints.length;
    }

    /**
     * Returns the paragraph start offset of the text.
     */
    public @IntRange(from = 0) int getParagraphStart(@IntRange(from = 0) int paraIndex) {
        Preconditions.checkArgumentInRange(paraIndex, 0, getParagraphCount(), "paraIndex");
        return paraIndex == 0 ? mStart : mParagraphBreakPoints[paraIndex - 1];
    }

    /**
     * Returns the paragraph end offset of the text.
     */
    public @IntRange(from = 0) int getParagraphEnd(@IntRange(from = 0) int paraIndex) {
        Preconditions.checkArgumentInRange(paraIndex, 0, getParagraphCount(), "paraIndex");
        return mParagraphBreakPoints[paraIndex];
    }

    /** @hide */
    public @NonNull MeasuredParagraph getMeasuredParagraph(@IntRange(from = 0) int paraIndex) {
        return mMeasuredParagraphs[paraIndex];
    }

    /**
     * Returns the break strategy for this text.
     */
    public @Layout.BreakStrategy int getBreakStrategy() {
        return mBreakStrategy;
    }

    /**
     * Returns the hyphenation frequency for this text.
     */
    public @Layout.HyphenationFrequency int getHyphenationFrequency() {
        return mHyphenationFrequency;
    }

    /**
     * Returns true if the given TextPaint gives the same result of text layout for this text.
     * @hide
     */
    public boolean canUseMeasuredResult(@NonNull TextPaint paint) {
        return mPaint.getTextSize() == paint.getTextSize()
            && mPaint.getTextSkewX() == paint.getTextSkewX()
            && mPaint.getTextScaleX() == paint.getTextScaleX()
            && mPaint.getLetterSpacing() == paint.getLetterSpacing()
            && mPaint.getWordSpacing() == paint.getWordSpacing()
            && mPaint.getFlags() == paint.getFlags()  // Maybe not all flag affects text layout.
            && mPaint.getTextLocales() == paint.getTextLocales()  // need to be equals?
            && mPaint.getFontVariationSettings() == paint.getFontVariationSettings()
            && mPaint.getTypeface() == paint.getTypeface()
            && TextUtils.equals(mPaint.getFontFeatureSettings(), paint.getFontFeatureSettings());
    }

    /** @hide */
    public int findParaIndex(@IntRange(from = 0) int pos) {
        // TODO: Maybe good to remove paragraph concept from MeasuredText and add substring layout
        //       support to StaticLayout.
        for (int i = 0; i < mParagraphBreakPoints.length; ++i) {
            if (pos < mParagraphBreakPoints[i]) {
                return i;
            }
        }
        throw new IndexOutOfBoundsException(
            "pos must be less than " + mParagraphBreakPoints[mParagraphBreakPoints.length - 1]
            + ", gave " + pos);
    }

    /** @hide */
    public float getWidth(@IntRange(from = 0) int start, @IntRange(from = 0) int end) {
        final int paraIndex = findParaIndex(start);
        final int paraStart = getParagraphStart(paraIndex);
        final int paraEnd = getParagraphEnd(paraIndex);
        if (start < paraStart || paraEnd < end) {
            throw new RuntimeException("Cannot measured across the paragraph:"
                + "para: (" + paraStart + ", " + paraEnd + "), "
                + "request: (" + start + ", " + end + ")");
        }
        return getMeasuredParagraph(paraIndex).getWidth(start - paraStart, end - paraStart);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////
    // Spanned overrides
    //
    // Just proxy for underlying mText if appropriate.

    @Override
    public <T> T[] getSpans(int start, int end, Class<T> type) {
        if (mText instanceof Spanned) {
            return ((Spanned) mText).getSpans(start, end, type);
        } else {
            return ArrayUtils.emptyArray(type);
        }
    }

    @Override
    public int getSpanStart(Object tag) {
        if (mText instanceof Spanned) {
            return ((Spanned) mText).getSpanStart(tag);
        } else {
            return -1;
        }
    }

    @Override
    public int getSpanEnd(Object tag) {
        if (mText instanceof Spanned) {
            return ((Spanned) mText).getSpanEnd(tag);
        } else {
            return -1;
        }
    }

    @Override
    public int getSpanFlags(Object tag) {
        if (mText instanceof Spanned) {
            return ((Spanned) mText).getSpanFlags(tag);
        } else {
            return 0;
        }
    }

    @Override
    public int nextSpanTransition(int start, int limit, Class type) {
        if (mText instanceof Spanned) {
            return ((Spanned) mText).nextSpanTransition(start, limit, type);
        } else {
            return mText.length();
        }
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////
    // CharSequence overrides.
    //
    // Just proxy for underlying mText.

    @Override
    public int length() {
        return mText.length();
    }

    @Override
    public char charAt(int index) {
        // TODO: Should this be index + mStart ?
        return mText.charAt(index);
    }

    @Override
    public CharSequence subSequence(int start, int end) {
        // TODO: return MeasuredText.
        // TODO: Should this be index + mStart, end + mStart ?
        return mText.subSequence(start, end);
    }

    @Override
    public String toString() {
        return mText.toString();
    }
}
