/*
 * 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() {
            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,
                        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;
        mPaint = 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;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////
    // 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();
    }
}
