/*
 * Copyright (C) 2016 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 com.android.calculator2;

import android.annotation.TargetApi;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.ClipboardManager;
import android.content.Context;
import android.graphics.Rect;
import android.os.Build;
import androidx.annotation.IntDef;
import androidx.core.content.ContextCompat;
import androidx.core.os.BuildCompat;
import android.text.Layout;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.style.BackgroundColorSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
import android.util.AttributeSet;
import android.view.ActionMode;
import android.view.ContextMenu;
import android.view.GestureDetector;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.OverScroller;
import android.widget.Toast;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

// A text widget that is "infinitely" scrollable to the right,
// and obtains the text to display via a callback to Logic.
public class CalculatorResult extends AlignedTextView implements MenuItem.OnMenuItemClickListener,
        Evaluator.EvaluationListener, Evaluator.CharMetricsInfo {
    static final int MAX_RIGHT_SCROLL = 10000000;
    static final int INVALID = MAX_RIGHT_SCROLL + 10000;
        // A larger value is unlikely to avoid running out of space
    final OverScroller mScroller;
    final GestureDetector mGestureDetector;
    private long mIndex;  // Index of expression we are displaying.
    private Evaluator mEvaluator;
    private boolean mScrollable = false;
                            // A scrollable result is currently displayed.
    private boolean mValid = false;
                            // The result holds a valid number (not an error message).
    // A suffix of "Pos" denotes a pixel offset.  Zero represents a scroll position
    // in which the decimal point is just barely visible on the right of the display.
    private int mCurrentPos;// Position of right of display relative to decimal point, in pixels.
                            // Large positive values mean the decimal point is scrolled off the
                            // left of the display.  Zero means decimal point is barely displayed
                            // on the right.
    private int mLastPos;   // Position already reflected in display. Pixels.
    private int mMinPos;    // Minimum position to avoid unnecessary blanks on the left. Pixels.
    private int mMaxPos;    // Maximum position before we start displaying the infinite
                            // sequence of trailing zeroes on the right. Pixels.
    private int mWholeLen;  // Length of the whole part of current result.
    // In the following, we use a suffix of Offset to denote a character position in a numeric
    // string relative to the decimal point.  Positive is to the right and negative is to
    // the left. 1 = tenths position, -1 = units.  Integer.MAX_VALUE is sometimes used
    // for the offset of the last digit in an a nonterminating decimal expansion.
    // We use the suffix "Index" to denote a zero-based index into a string representing a
    // result.
    private int mMaxCharOffset;  // Character offset from decimal point of rightmost digit
                                 // that should be displayed, plus the length of any exponent
                                 // needed to display that digit.
                                 // Limited to MAX_RIGHT_SCROLL. Often the same as:
    private int mLsdOffset;      // Position of least-significant digit in result
    private int mLastDisplayedOffset; // Offset of last digit actually displayed after adding
                                      // exponent.
    private boolean mWholePartFits;  // Scientific notation not needed for initial display.
    private float mNoExponentCredit;
                            // Fraction of digit width saved by avoiding scientific notation.
                            // Only accessed from UI thread.
    private boolean mAppendExponent;
                            // The result fits entirely in the display, even with an exponent,
                            // but not with grouping separators. Since the result is not
                            // scrollable, and we do not add the exponent to max. scroll position,
                            // append an exponent insteadd of replacing trailing digits.
    private final Object mWidthLock = new Object();
                            // Protects the next five fields.  These fields are only
                            // updated by the UI thread, and read accesses by the UI thread
                            // sometimes do not acquire the lock.
    private int mWidthConstraint = 0;
                            // Our total width in pixels minus space for ellipsis.
                            // 0 ==> uninitialized.
    private float mCharWidth = 1;
                            // Maximum character width. For now we pretend that all characters
                            // have this width.
                            // TODO: We're not really using a fixed width font.  But it appears
                            // to be close enough for the characters we use that the difference
                            // is not noticeable.
    private float mGroupingSeparatorWidthRatio;
                            // Fraction of digit width occupied by a digit separator.
    private float mDecimalCredit;
                            // Fraction of digit width saved by replacing digit with decimal point.
    private float mNoEllipsisCredit;
                            // Fraction of digit width saved by both replacing ellipsis with digit
                            // and avoiding scientific notation.
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({SHOULD_REQUIRE, SHOULD_EVALUATE, SHOULD_NOT_EVALUATE})
    public @interface EvaluationRequest {}
    public static final int SHOULD_REQUIRE = 2;
    public static final int SHOULD_EVALUATE = 1;
    public static final int SHOULD_NOT_EVALUATE = 0;
    @EvaluationRequest private int mEvaluationRequest = SHOULD_REQUIRE;
                            // Should we evaluate when layout completes, and how?
    private Evaluator.EvaluationListener mEvaluationListener = this;
                            // Listener to use if/when evaluation is requested.
    public static final int MAX_LEADING_ZEROES = 6;
                            // Maximum number of leading zeroes after decimal point before we
                            // switch to scientific notation with negative exponent.
    public static final int MAX_TRAILING_ZEROES = 6;
                            // Maximum number of trailing zeroes before the decimal point before
                            // we switch to scientific notation with positive exponent.
    private static final int SCI_NOTATION_EXTRA = 1;
                            // Extra digits for standard scientific notation.  In this case we
                            // have a decimal point and no ellipsis.
                            // We assume that we do not drop digits to make room for the decimal
                            // point in ordinary scientific notation. Thus >= 1.
    private static final int MAX_COPY_EXTRA = 100;
                            // The number of extra digits we are willing to compute to copy
                            // a result as an exact number.
    private static final int MAX_RECOMPUTE_DIGITS = 2000;
                            // The maximum number of digits we're willing to recompute in the UI
                            // thread.  We only do this for known rational results, where we
                            // can bound the computation cost.
    private final ForegroundColorSpan mExponentColorSpan;
    private final BackgroundColorSpan mHighlightSpan;

    private ActionMode mActionMode;
    private ActionMode.Callback mCopyActionModeCallback;
    private ContextMenu mContextMenu;

    // The user requested that the result currently being evaluated should be stored to "memory".
    private boolean mStoreToMemoryRequested = false;

    public CalculatorResult(Context context, AttributeSet attrs) {
        super(context, attrs);
        mScroller = new OverScroller(context);
        mHighlightSpan = new BackgroundColorSpan(getHighlightColor());
        mExponentColorSpan = new ForegroundColorSpan(
                ContextCompat.getColor(context, R.color.display_result_exponent_text_color));
        mGestureDetector = new GestureDetector(context,
            new GestureDetector.SimpleOnGestureListener() {
                @Override
                public boolean onDown(MotionEvent e) {
                    return true;
                }
                @Override
                public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                        float velocityY) {
                    if (!mScroller.isFinished()) {
                        mCurrentPos = mScroller.getFinalX();
                    }
                    mScroller.forceFinished(true);
                    stopActionModeOrContextMenu();
                    CalculatorResult.this.cancelLongPress();
                    // Ignore scrolls of error string, etc.
                    if (!mScrollable) return true;
                    mScroller.fling(mCurrentPos, 0, - (int) velocityX, 0  /* horizontal only */,
                                    mMinPos, mMaxPos, 0, 0);
                    postInvalidateOnAnimation();
                    return true;
                }
                @Override
                public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
                        float distanceY) {
                    int distance = (int)distanceX;
                    if (!mScroller.isFinished()) {
                        mCurrentPos = mScroller.getFinalX();
                    }
                    mScroller.forceFinished(true);
                    stopActionModeOrContextMenu();
                    CalculatorResult.this.cancelLongPress();
                    if (!mScrollable) return true;
                    if (mCurrentPos + distance < mMinPos) {
                        distance = mMinPos - mCurrentPos;
                    } else if (mCurrentPos + distance > mMaxPos) {
                        distance = mMaxPos - mCurrentPos;
                    }
                    int duration = (int)(e2.getEventTime() - e1.getEventTime());
                    if (duration < 1 || duration > 100) duration = 10;
                    mScroller.startScroll(mCurrentPos, 0, distance, 0, (int)duration);
                    postInvalidateOnAnimation();
                    return true;
                }
                @Override
                public void onLongPress(MotionEvent e) {
                    if (mValid) {
                        performLongClick();
                    }
                }
            });

        final int slop = ViewConfiguration.get(context).getScaledTouchSlop();
        setOnTouchListener(new View.OnTouchListener() {

            // Used to determine whether a touch event should be intercepted.
            private float mInitialDownX;
            private float mInitialDownY;

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                final int action = event.getActionMasked();

                final float x = event.getX();
                final float y = event.getY();
                switch (action) {
                    case MotionEvent.ACTION_DOWN:
                        mInitialDownX = x;
                        mInitialDownY = y;
                        break;
                    case MotionEvent.ACTION_MOVE:
                        final float deltaX = Math.abs(x - mInitialDownX);
                        final float deltaY = Math.abs(y - mInitialDownY);
                        if (deltaX > slop && deltaX > deltaY) {
                            // Prevent the DragLayout from intercepting horizontal scrolls.
                            getParent().requestDisallowInterceptTouchEvent(true);
                        }
                }
                return mGestureDetector.onTouchEvent(event);
            }
        });

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            setupActionMode();
        } else {
            setupContextMenu();
        }

        setCursorVisible(false);
        setLongClickable(false);
        setContentDescription(context.getString(R.string.desc_result));
    }

    void setEvaluator(Evaluator evaluator, long index) {
        mEvaluator = evaluator;
        mIndex = index;
        requestLayout();
    }

    // Compute maximum digit width the hard way.
    private static float getMaxDigitWidth(TextPaint paint) {
        // Compute the maximum advance width for each digit, thus accounting for between-character
        // spaces. If we ever support other kinds of digits, we may have to avoid kerning effects
        // that could reduce the advance width within this particular string.
        final String allDigits = "0123456789";
        final float[] widths = new float[allDigits.length()];
        paint.getTextWidths(allDigits, widths);
        float maxWidth = 0;
        for (float x : widths) {
            maxWidth = Math.max(x, maxWidth);
        }
        return maxWidth;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (!isLaidOut()) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            // Set a minimum height so scaled error messages won't affect our layout.
            setMinimumHeight(getLineHeight() + getCompoundPaddingBottom()
                    + getCompoundPaddingTop());
        }

        final TextPaint paint = getPaint();
        final Context context = getContext();
        final float newCharWidth = getMaxDigitWidth(paint);
        // Digits are presumed to have no more than newCharWidth.
        // There are two instances when we know that the result is otherwise narrower than
        // expected:
        // 1. For standard scientific notation (our type 1), we know that we have a norrow decimal
        // point and no (usually wide) ellipsis symbol. We allow one extra digit
        // (SCI_NOTATION_EXTRA) to compensate, and consider that in determining available width.
        // 2. If we are using digit grouping separators and a decimal point, we give ourselves
        // a fractional extra space for those separators, the value of which depends on whether
        // there is also an ellipsis.
        //
        // Maximum extra space we need in various cases:
        // Type 1 scientific notation, assuming ellipsis, minus sign and E are wider than a digit:
        //    Two minus signs + "E" + "." - 3 digits.
        // Type 2 scientific notation:
        //    Ellipsis + "E" + "-" - 3 digits.
        // In the absence of scientific notation, we may need a little less space.
        // We give ourselves a bit of extra credit towards comma insertion and give
        // ourselves more if we have either
        //    No ellipsis, or
        //    A decimal separator.

        // Calculate extra space we need to reserve, in addition to character count.
        final float decimalSeparatorWidth = Layout.getDesiredWidth(
                context.getString(R.string.dec_point), paint);
        final float minusWidth = Layout.getDesiredWidth(context.getString(R.string.op_sub), paint);
        final float minusExtraWidth = Math.max(minusWidth - newCharWidth, 0.0f);
        final float ellipsisWidth = Layout.getDesiredWidth(KeyMaps.ELLIPSIS, paint);
        final float ellipsisExtraWidth =  Math.max(ellipsisWidth - newCharWidth, 0.0f);
        final float expWidth = Layout.getDesiredWidth(KeyMaps.translateResult("e"), paint);
        final float expExtraWidth =  Math.max(expWidth - newCharWidth, 0.0f);
        final float type1Extra = 2 * minusExtraWidth + expExtraWidth + decimalSeparatorWidth;
        final float type2Extra = ellipsisExtraWidth + expExtraWidth + minusExtraWidth;
        final float extraWidth = Math.max(type1Extra, type2Extra);
        final int intExtraWidth = (int) Math.ceil(extraWidth) + 1 /* to cover rounding sins */;
        final int newWidthConstraint = MeasureSpec.getSize(widthMeasureSpec)
                - (getPaddingLeft() + getPaddingRight()) - intExtraWidth;

        // Calculate other width constants we need to handle grouping separators.
        final float groupingSeparatorW =
                Layout.getDesiredWidth(KeyMaps.translateResult(","), paint);
        // Credits in the absence of any scientific notation:
        float noExponentCredit = extraWidth - Math.max(ellipsisExtraWidth, minusExtraWidth);
        final float noEllipsisCredit = extraWidth - minusExtraWidth;  // includes noExponentCredit.
        final float decimalCredit = Math.max(newCharWidth - decimalSeparatorWidth, 0.0f);

        mNoExponentCredit = noExponentCredit / newCharWidth;
        synchronized(mWidthLock) {
            mWidthConstraint = newWidthConstraint;
            mCharWidth = newCharWidth;
            mNoEllipsisCredit = noEllipsisCredit / newCharWidth;
            mDecimalCredit = decimalCredit / newCharWidth;
            mGroupingSeparatorWidthRatio = groupingSeparatorW / newCharWidth;
        }

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        if (mEvaluator != null && mEvaluationRequest != SHOULD_NOT_EVALUATE) {
            final CalculatorExpr expr = mEvaluator.getExpr(mIndex);
            if (expr != null && expr.hasInterestingOps()) {
                if (mEvaluationRequest == SHOULD_REQUIRE) {
                    mEvaluator.requireResult(mIndex, mEvaluationListener, this);
                } else {
                    mEvaluator.evaluateAndNotify(mIndex, mEvaluationListener, this);
                }
            }
        }
    }

    /**
     * Specify whether we should evaluate result on layout.
     * @param should one of SHOULD_REQUIRE, SHOULD_EVALUATE, SHOULD_NOT_EVALUATE
     */
    public void setShouldEvaluateResult(@EvaluationRequest int request,
            Evaluator.EvaluationListener listener) {
        mEvaluationListener = listener;
        mEvaluationRequest = request;
    }

    // From Evaluator.CharMetricsInfo.
    @Override
    public float separatorChars(String s, int len) {
        int start = 0;
        while (start < len && !Character.isDigit(s.charAt(start))) {
            ++start;
        }
        // We assume the rest consists of digits, and for consistency with the rest
        // of the code, we assume all digits have width mCharWidth.
        final int nDigits = len - start;
        // We currently insert a digit separator every three digits.
        final int nSeparators = (nDigits - 1) / 3;
        synchronized(mWidthLock) {
            // Always return an upper bound, even in the presence of rounding errors.
            return nSeparators * mGroupingSeparatorWidthRatio;
        }
    }

    // From Evaluator.CharMetricsInfo.
    @Override
    public float getNoEllipsisCredit() {
        synchronized(mWidthLock) {
            return mNoEllipsisCredit;
        }
    }

    // From Evaluator.CharMetricsInfo.
    @Override
    public float getDecimalCredit() {
        synchronized(mWidthLock) {
            return mDecimalCredit;
        }
    }

    // Return the length of the exponent representation for the given exponent, in
    // characters.
    private final int expLen(int exp) {
        if (exp == 0) return 0;
        final int abs_exp_digits = (int) Math.ceil(Math.log10(Math.abs((double)exp))
                + 0.0000000001d /* Round whole numbers to next integer */);
        return abs_exp_digits + (exp >= 0 ? 1 : 2);
    }

    /**
     * Initiate display of a new result.
     * Only called from UI thread.
     * The parameters specify various properties of the result.
     * @param index Index of expression that was just evaluated. Currently ignored, since we only
     *            expect notification for the expression result being displayed.
     * @param initPrec Initial display precision computed by evaluator. (1 = tenths digit)
     * @param msd Position of most significant digit.  Offset from left of string.
                  Evaluator.INVALID_MSD if unknown.
     * @param leastDigPos Position of least significant digit (1 = tenths digit)
     *                    or Integer.MAX_VALUE.
     * @param truncatedWholePart Result up to but not including decimal point.
                                 Currently we only use the length.
     */
    @Override
    public void onEvaluate(long index, int initPrec, int msd, int leastDigPos,
            String truncatedWholePart) {
        initPositions(initPrec, msd, leastDigPos, truncatedWholePart);

        if (mStoreToMemoryRequested) {
            mEvaluator.copyToMemory(index);
            mStoreToMemoryRequested = false;
        }
        redisplay();
    }

    /**
     * Store the result for this index if it is available.
     * If it is unavailable, set mStoreToMemoryRequested to indicate that we should store
     * when evaluation is complete.
     */
    public void onMemoryStore() {
        if (mEvaluator.hasResult(mIndex)) {
            mEvaluator.copyToMemory(mIndex);
        } else {
            mStoreToMemoryRequested = true;
            mEvaluator.requireResult(mIndex, this /* listener */, this /* CharMetricsInfo */);
        }
    }

    /**
     * Add the result to the value currently in memory.
     */
    public void onMemoryAdd() {
        mEvaluator.addToMemory(mIndex);
    }

    /**
     * Subtract the result from the value currently in memory.
     */
    public void onMemorySubtract() {
        mEvaluator.subtractFromMemory(mIndex);
    }

    /**
     * Set up scroll bounds (mMinPos, mMaxPos, etc.) and determine whether the result is
     * scrollable, based on the supplied information about the result.
     * This is unfortunately complicated because we need to predict whether trailing digits
     * will eventually be replaced by an exponent.
     * Just appending the exponent during formatting would be simpler, but would produce
     * jumpier results during transitions.
     * Only called from UI thread.
     */
    private void initPositions(int initPrecOffset, int msdIndex, int lsdOffset,
            String truncatedWholePart) {
        int maxChars = getMaxChars();
        mWholeLen = truncatedWholePart.length();
        // Allow a tiny amount of slop for associativity/rounding differences in length
        // calculation.  If getPreferredPrec() decided it should fit, we want to make it fit, too.
        // We reserved one extra pixel, so the extra length is OK.
        final int nSeparatorChars = (int) Math.ceil(
                separatorChars(truncatedWholePart, truncatedWholePart.length())
                - getNoEllipsisCredit() - 0.0001f);
        mWholePartFits = mWholeLen + nSeparatorChars <= maxChars;
        mLastPos = INVALID;
        mLsdOffset = lsdOffset;
        mAppendExponent = false;
        // Prevent scrolling past initial position, which is calculated to show leading digits.
        mCurrentPos = mMinPos = (int) Math.round(initPrecOffset * mCharWidth);
        if (msdIndex == Evaluator.INVALID_MSD) {
            // Possible zero value
            if (lsdOffset == Integer.MIN_VALUE) {
                // Definite zero value.
                mMaxPos = mMinPos;
                mMaxCharOffset = (int) Math.round(mMaxPos/mCharWidth);
                mScrollable = false;
            } else {
                // May be very small nonzero value.  Allow user to find out.
                mMaxPos = mMaxCharOffset = MAX_RIGHT_SCROLL;
                mMinPos -= mCharWidth;  // Allow for future minus sign.
                mScrollable = true;
            }
            return;
        }
        int negative = truncatedWholePart.charAt(0) == '-' ? 1 : 0;
        if (msdIndex > mWholeLen && msdIndex <= mWholeLen + 3) {
            // Avoid tiny negative exponent; pretend msdIndex is just to the right of decimal point.
            msdIndex = mWholeLen - 1;
        }
        // Set to position of leftmost significant digit relative to dec. point. Usually negative.
        int minCharOffset = msdIndex - mWholeLen;
        if (minCharOffset > -1 && minCharOffset < MAX_LEADING_ZEROES + 2) {
            // Small number of leading zeroes, avoid scientific notation.
            minCharOffset = -1;
        }
        if (lsdOffset < MAX_RIGHT_SCROLL) {
            mMaxCharOffset = lsdOffset;
            if (mMaxCharOffset < -1 && mMaxCharOffset > -(MAX_TRAILING_ZEROES + 2)) {
                mMaxCharOffset = -1;
            }
            // lsdOffset is positive or negative, never 0.
            int currentExpLen = 0;  // Length of required standard scientific notation exponent.
            if (mMaxCharOffset < -1) {
                currentExpLen = expLen(-minCharOffset - 1);
            } else if (minCharOffset > -1 || mMaxCharOffset >= maxChars) {
                // Number is either entirely to the right of decimal point, or decimal point is
                // not visible when scrolled to the right.
                currentExpLen = expLen(-minCharOffset);
            }
            // Exponent length does not included added decimal point.  But whenever we add a
            // decimal point, we allow an extra character (SCI_NOTATION_EXTRA).
            final int separatorLength = mWholePartFits && minCharOffset < -3 ? nSeparatorChars : 0;
            mScrollable = (mMaxCharOffset + currentExpLen + separatorLength - minCharOffset
                    + negative >= maxChars);
            // Now adjust mMaxCharOffset for any required exponent.
            int newMaxCharOffset;
            if (currentExpLen > 0) {
                if (mScrollable) {
                    // We'll use exponent corresponding to leastDigPos when scrolled to right.
                    newMaxCharOffset = mMaxCharOffset + expLen(-lsdOffset);
                } else {
                    newMaxCharOffset = mMaxCharOffset + currentExpLen;
                }
                if (mMaxCharOffset <= -1 && newMaxCharOffset > -1) {
                    // Very unlikely; just drop exponent.
                    mMaxCharOffset = -1;
                } else {
                    mMaxCharOffset = Math.min(newMaxCharOffset, MAX_RIGHT_SCROLL);
                }
                mMaxPos = Math.min((int) Math.round(mMaxCharOffset * mCharWidth),
                        MAX_RIGHT_SCROLL);
            } else if (!mWholePartFits && !mScrollable) {
                // Corner case in which entire number fits, but not with grouping separators.  We
                // will use an exponent in un-scrolled position, which may hide digits.  Scrolling
                // by one character will remove the exponent and reveal the last digits.  Note
                // that in the forced scientific notation case, the exponent length is not
                // factored into mMaxCharOffset, since we do not want such an increase to impact
                // scrolling behavior.  In the unscrollable case, we thus have to append the
                // exponent at the end using the forcePrecision argument to formatResult, in order
                // to ensure that we get the entire result.
                mScrollable = (mMaxCharOffset + expLen(-minCharOffset - 1) - minCharOffset
                        + negative >= maxChars);
                if (mScrollable) {
                    mMaxPos = (int) Math.ceil(mMinPos + mCharWidth);
                    // Single character scroll will remove exponent and show remaining piece.
                } else {
                    mMaxPos = mMinPos;
                    mAppendExponent = true;
                }
            } else {
                mMaxPos = Math.min((int) Math.round(mMaxCharOffset * mCharWidth),
                        MAX_RIGHT_SCROLL);
            }
            if (!mScrollable) {
                // Position the number consistently with our assumptions to make sure it
                // actually fits.
                mCurrentPos = mMaxPos;
            }
        } else {
            mMaxPos = mMaxCharOffset = MAX_RIGHT_SCROLL;
            mScrollable = true;
        }
    }

    /**
     * Display error message indicated by resourceId.
     * UI thread only.
     */
    @Override
    public void onError(long index, int resourceId) {
        mStoreToMemoryRequested = false;
        mValid = false;
        setLongClickable(false);
        mScrollable = false;
        final String msg = getContext().getString(resourceId);
        final float measuredWidth = Layout.getDesiredWidth(msg, getPaint());
        if (measuredWidth > mWidthConstraint) {
            // Multiply by .99 to avoid rounding effects.
            final float scaleFactor = 0.99f * mWidthConstraint / measuredWidth;
            final RelativeSizeSpan smallTextSpan = new RelativeSizeSpan(scaleFactor);
            final SpannableString scaledMsg = new SpannableString(msg);
            scaledMsg.setSpan(smallTextSpan, 0, msg.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            setText(scaledMsg);
        } else {
            setText(msg);
        }
    }

    private final int MAX_COPY_SIZE = 1000000;

    /*
     * Return the most significant digit position in the given string or Evaluator.INVALID_MSD.
     * Unlike Evaluator.getMsdIndexOf, we treat a final 1 as significant.
     * Pure function; callable from anywhere.
     */
    public static int getNaiveMsdIndexOf(String s) {
        final int len = s.length();
        for (int i = 0; i < len; ++i) {
            char c = s.charAt(i);
            if (c != '-' && c != '.' && c != '0') {
                return i;
            }
        }
        return Evaluator.INVALID_MSD;
    }

    /**
     * Format a result returned by Evaluator.getString() into a single line containing ellipses
     * (if appropriate) and an exponent (if appropriate).
     * We add two distinct kinds of exponents:
     * (1) If the final result contains the leading digit we use standard scientific notation.
     * (2) If not, we add an exponent corresponding to an interpretation of the final result as
     *     an integer.
     * We add an ellipsis on the left if the result was truncated.
     * We add ellipses and exponents in a way that leaves most digits in the position they
     * would have been in had we not done so. This minimizes jumps as a result of scrolling.
     * Result is NOT internationalized, uses "E" for exponent.
     * Called only from UI thread; We sometimes omit locking for fields.
     * @param precOffset The value that was passed to getString. Identifies the significance of
                the rightmost digit. A value of 1 means the rightmost digits corresponds to tenths.
     * @param maxDigs The maximum number of characters in the result
     * @param truncated The in parameter was already truncated, beyond possibly removing the
                minus sign.
     * @param negative The in parameter represents a negative result. (Minus sign may be removed
                without setting truncated.)
     * @param lastDisplayedOffset  If not null, we set lastDisplayedOffset[0] to the offset of
                the last digit actually appearing in the display.
     * @param forcePrecision If true, we make sure that the last displayed digit corresponds to
                precOffset, and allow maxDigs to be exceeded in adding the exponent and commas.
     * @param forceSciNotation Force scientific notation. May be set because we don't have
                space for grouping separators, but whole number otherwise fits.
     * @param insertCommas Insert commas (literally, not internationalized) as digit separators.
                We only ever do this for the integral part of a number, and only when no
                exponent is displayed in the initial position. The combination of which means
                that we only do it when no exponent is displayed.
                We insert commas in a way that does consider the width of the actual localized digit
                separator. Commas count towards maxDigs as the appropriate fraction of a digit.
     */
    private String formatResult(String in, int precOffset, int maxDigs, boolean truncated,
            boolean negative, int lastDisplayedOffset[], boolean forcePrecision,
            boolean forceSciNotation, boolean insertCommas) {
        final int minusSpace = negative ? 1 : 0;
        final int msdIndex = truncated ? -1 : getNaiveMsdIndexOf(in);  // INVALID_MSD is OK.
        String result = in;
        boolean needEllipsis = false;
        if (truncated || (negative && result.charAt(0) != '-')) {
            needEllipsis = true;
            result = KeyMaps.ELLIPSIS + result.substring(1, result.length());
            // Ellipsis may be removed again in the type(1) scientific notation case.
        }
        final int decIndex = result.indexOf('.');
        if (lastDisplayedOffset != null) {
            lastDisplayedOffset[0] = precOffset;
        }
        if (forceSciNotation || (decIndex == -1 || msdIndex != Evaluator.INVALID_MSD
                && msdIndex - decIndex > MAX_LEADING_ZEROES + 1) &&  precOffset != -1) {
            // Either:
            // 1) No decimal point displayed, and it's not just to the right of the last digit, or
            // 2) we are at the front of a number whos integral part is too large to allow
            // comma insertion, or
            // 3) we should suppress leading zeroes.
            // Add an exponent to let the user track which digits are currently displayed.
            // Start with type (2) exponent if we dropped no digits. -1 accounts for decimal point.
            // We currently never show digit separators together with an exponent.
            final int initExponent = precOffset > 0 ? -precOffset : -precOffset - 1;
            int exponent = initExponent;
            boolean hasPoint = false;
            if (!truncated && msdIndex < maxDigs - 1
                    && result.length() - msdIndex + 1 + minusSpace
                    <= maxDigs + SCI_NOTATION_EXTRA) {
                // Type (1) exponent computation and transformation:
                // Leading digit is in display window. Use standard calculator scientific notation
                // with one digit to the left of the decimal point. Insert decimal point and
                // delete leading zeroes.
                // We try to keep leading digits roughly in position, and never
                // lengthen the result by more than SCI_NOTATION_EXTRA.
                if (decIndex > msdIndex) {
                    // In the forceSciNotation, we can have a decimal point in the relevant digit
                    // range. Remove it.
                    result = result.substring(0, decIndex)
                            + result.substring(decIndex + 1, result.length());
                    // msdIndex and precOffset unaffected.
                }
                final int resLen = result.length();
                String fraction = result.substring(msdIndex + 1, resLen);
                result = (negative ? "-" : "") + result.substring(msdIndex, msdIndex + 1)
                        + "." + fraction;
                // Original exp was correct for decimal point at right of fraction.
                // Adjust by length of fraction.
                exponent = initExponent + resLen - msdIndex - 1;
                hasPoint = true;
            }
            // Exponent can't be zero.
            // Actually add the exponent of either type:
            if (!forcePrecision) {
                int dropDigits;  // Digits to drop to make room for exponent.
                if (hasPoint) {
                    // Type (1) exponent.
                    // Drop digits even if there is room. Otherwise the scrolling gets jumpy.
                    dropDigits = expLen(exponent);
                    if (dropDigits >= result.length() - 1) {
                        // Jumpy is better than no mantissa.  Probably impossible anyway.
                        dropDigits = Math.max(result.length() - 2, 0);
                    }
                } else {
                    // Type (2) exponent.
                    // Exponent depends on the number of digits we drop, which depends on
                    // exponent ...
                    for (dropDigits = 2; expLen(initExponent + dropDigits) > dropDigits;
                            ++dropDigits) {}
                    exponent = initExponent + dropDigits;
                    if (precOffset - dropDigits > mLsdOffset) {
                        // This can happen if e.g. result = 10^40 + 10^10
                        // It turns out we would otherwise display ...10e9 because it takes
                        // the same amount of space as ...1e10 but shows one more digit.
                        // But we don't want to display a trailing zero, even if it's free.
                        ++dropDigits;
                        ++exponent;
                    }
                }
                if (dropDigits >= result.length() - 1) {
                    // Display too small to show meaningful result.
                    return KeyMaps.ELLIPSIS + "E" + KeyMaps.ELLIPSIS;
                }
                result = result.substring(0, result.length() - dropDigits);
                if (lastDisplayedOffset != null) {
                    lastDisplayedOffset[0] -= dropDigits;
                }
            }
            result = result + "E" + Integer.toString(exponent);
        } else if (insertCommas) {
            // Add commas to the whole number section, and then truncate on left to fit,
            // counting commas as a fractional digit.
            final int wholeStart = needEllipsis ? 1 : 0;
            int orig_length = result.length();
            final float nCommaChars;
            if (decIndex != -1) {
                nCommaChars = separatorChars(result, decIndex);
                result = StringUtils.addCommas(result, wholeStart, decIndex)
                        + result.substring(decIndex, orig_length);
            } else {
                nCommaChars = separatorChars(result, orig_length);
                result = StringUtils.addCommas(result, wholeStart, orig_length);
            }
            if (needEllipsis) {
                orig_length -= 1;  // Exclude ellipsis.
            }
            final float len = orig_length + nCommaChars;
            int deletedChars = 0;
            final float ellipsisCredit = getNoEllipsisCredit();
            final float decimalCredit = getDecimalCredit();
            final float effectiveLen = len - (decIndex == -1 ? 0 : getDecimalCredit());
            final float ellipsisAdjustment =
                    needEllipsis ? mNoExponentCredit : getNoEllipsisCredit();
            // As above, we allow for a tiny amount of extra length here, for consistency with
            // getPreferredPrec().
            if (effectiveLen - ellipsisAdjustment > (float) (maxDigs - wholeStart) + 0.0001f
                && !forcePrecision) {
                float deletedWidth = 0.0f;
                while (effectiveLen - mNoExponentCredit - deletedWidth
                        > (float) (maxDigs - 1 /* for ellipsis */)) {
                    if (result.charAt(deletedChars) == ',') {
                        deletedWidth += mGroupingSeparatorWidthRatio;
                    } else {
                        deletedWidth += 1.0f;
                    }
                    deletedChars++;
                }
            }
            if (deletedChars > 0) {
                result = KeyMaps.ELLIPSIS + result.substring(deletedChars, result.length());
            } else if (needEllipsis) {
                result = KeyMaps.ELLIPSIS + result;
            }
        }
        return result;
    }

    /**
     * Get formatted, but not internationalized, result from mEvaluator.
     * @param precOffset requested position (1 = tenths) of last included digit
     * @param maxSize maximum number of characters (more or less) in result
     * @param lastDisplayedOffset zeroth entry is set to actual offset of last included digit,
     *                            after adjusting for exponent, etc.  May be null.
     * @param forcePrecision Ensure that last included digit is at pos, at the expense
     *                       of treating maxSize as a soft limit.
     * @param forceSciNotation Force scientific notation, even if not required by maxSize.
     * @param insertCommas Insert commas as digit separators.
     */
    private String getFormattedResult(int precOffset, int maxSize, int lastDisplayedOffset[],
            boolean forcePrecision, boolean forceSciNotation, boolean insertCommas) {
        final boolean truncated[] = new boolean[1];
        final boolean negative[] = new boolean[1];
        final int requestedPrecOffset[] = {precOffset};
        final String rawResult = mEvaluator.getString(mIndex, requestedPrecOffset, mMaxCharOffset,
                maxSize, truncated, negative, this);
        return formatResult(rawResult, requestedPrecOffset[0], maxSize, truncated[0], negative[0],
                lastDisplayedOffset, forcePrecision, forceSciNotation, insertCommas);
   }

    /**
     * Return entire result (within reason) up to current displayed precision.
     * @param withSeparators  Add digit separators
     */
    public String getFullText(boolean withSeparators) {
        if (!mValid) return "";
        if (!mScrollable) return getText().toString();
        return KeyMaps.translateResult(getFormattedResult(mLastDisplayedOffset, MAX_COPY_SIZE,
                null, true /* forcePrecision */, false /* forceSciNotation */, withSeparators));
    }

    /**
     * Did the above produce a correct result?
     * UI thread only.
     */
    public boolean fullTextIsExact() {
        return !mScrollable || (getCharOffset(mMaxPos) == getCharOffset(mCurrentPos)
                && mMaxCharOffset != MAX_RIGHT_SCROLL);
    }

    /**
     * Get entire result up to current displayed precision, or up to MAX_COPY_EXTRA additional
     * digits, if it will lead to an exact result.
     */
    public String getFullCopyText() {
        if (!mValid
                || mLsdOffset == Integer.MAX_VALUE
                || fullTextIsExact()
                || mWholeLen > MAX_RECOMPUTE_DIGITS
                || mWholeLen + mLsdOffset > MAX_RECOMPUTE_DIGITS
                || mLsdOffset - mLastDisplayedOffset > MAX_COPY_EXTRA) {
            return getFullText(false /* withSeparators */);
        }
        // It's reasonable to compute and copy the exact result instead.
        int fractionLsdOffset = Math.max(0, mLsdOffset);
        String rawResult = mEvaluator.getResult(mIndex).toStringTruncated(fractionLsdOffset);
        if (mLsdOffset <= -1) {
            // Result has trailing decimal point. Remove it.
            rawResult = rawResult.substring(0, rawResult.length() - 1);
            fractionLsdOffset = -1;
        }
        final String formattedResult = formatResult(rawResult, fractionLsdOffset, MAX_COPY_SIZE,
                false, rawResult.charAt(0) == '-', null, true /* forcePrecision */,
                false /* forceSciNotation */, false /* insertCommas */);
        return KeyMaps.translateResult(formattedResult);
    }

    /**
     * Return the maximum number of characters that will fit in the result display.
     * May be called asynchronously from non-UI thread. From Evaluator.CharMetricsInfo.
     * Returns zero if measurement hasn't completed.
     */
    @Override
    public int getMaxChars() {
        int result;
        synchronized(mWidthLock) {
            return (int) Math.floor(mWidthConstraint / mCharWidth);
        }
    }

    /**
     * @return {@code true} if the currently displayed result is scrollable
     */
    public boolean isScrollable() {
        return mScrollable;
    }

    /**
     * Map pixel position to digit offset.
     * UI thread only.
     */
    int getCharOffset(int pos) {
        return (int) Math.round(pos / mCharWidth);  // Lock not needed.
    }

    void clear() {
        mValid = false;
        mScrollable = false;
        setText("");
        setLongClickable(false);
    }

    @Override
    public void onCancelled(long index) {
        clear();
        mStoreToMemoryRequested = false;
    }

    /**
     * Refresh display.
     * Only called in UI thread. Index argument is currently ignored.
     */
    @Override
    public void onReevaluate(long index) {
        redisplay();
    }

    public void redisplay() {
        int maxChars = getMaxChars();
        if (maxChars < 4) {
            // Display currently too small to display a reasonable result. Punt to avoid crash.
            return;
        }
        if (mScroller.isFinished() && length() > 0) {
            setAccessibilityLiveRegion(ACCESSIBILITY_LIVE_REGION_POLITE);
        }
        int currentCharOffset = getCharOffset(mCurrentPos);
        int lastDisplayedOffset[] = new int[1];
        String result = getFormattedResult(currentCharOffset, maxChars, lastDisplayedOffset,
                mAppendExponent /* forcePrecision; preserve entire result */,
                !mWholePartFits
                &&  currentCharOffset == getCharOffset(mMinPos) /* forceSciNotation */,
                mWholePartFits /* insertCommas */ );
        int expIndex = result.indexOf('E');
        result = KeyMaps.translateResult(result);
        if (expIndex > 0 && result.indexOf('.') == -1) {
          // Gray out exponent if used as position indicator
            SpannableString formattedResult = new SpannableString(result);
            formattedResult.setSpan(mExponentColorSpan, expIndex, result.length(),
                                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            setText(formattedResult);
        } else {
            setText(result);
        }
        mLastDisplayedOffset = lastDisplayedOffset[0];
        mValid = true;
        setLongClickable(true);
    }

    @Override
    protected void onTextChanged(java.lang.CharSequence text, int start, int lengthBefore,
            int lengthAfter) {
        super.onTextChanged(text, start, lengthBefore, lengthAfter);

        if (!mScrollable || mScroller.isFinished()) {
            if (lengthBefore == 0 && lengthAfter > 0) {
                setAccessibilityLiveRegion(ACCESSIBILITY_LIVE_REGION_POLITE);
                setContentDescription(null);
            } else if (lengthBefore > 0 && lengthAfter == 0) {
                setAccessibilityLiveRegion(ACCESSIBILITY_LIVE_REGION_NONE);
                setContentDescription(getContext().getString(R.string.desc_result));
            }
        }
    }

    @Override
    public void computeScroll() {
        if (!mScrollable) {
            return;
        }

        if (mScroller.computeScrollOffset()) {
            mCurrentPos = mScroller.getCurrX();
            if (getCharOffset(mCurrentPos) != getCharOffset(mLastPos)) {
                mLastPos = mCurrentPos;
                redisplay();
            }
        }

        if (!mScroller.isFinished()) {
                postInvalidateOnAnimation();
                setAccessibilityLiveRegion(ACCESSIBILITY_LIVE_REGION_NONE);
        } else if (length() > 0){
            setAccessibilityLiveRegion(ACCESSIBILITY_LIVE_REGION_POLITE);
        }
    }

    /**
     * Use ActionMode for copy/memory support on M and higher.
     */
    @TargetApi(Build.VERSION_CODES.M)
    private void setupActionMode() {
        mCopyActionModeCallback = new ActionMode.Callback2() {

            @Override
            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                final MenuInflater inflater = mode.getMenuInflater();
                return createContextMenu(inflater, menu);
            }

            @Override
            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                return false; // Return false if nothing is done
            }

            @Override
            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
                if (onMenuItemClick(item)) {
                    mode.finish();
                    return true;
                } else {
                    return false;
                }
            }

            @Override
            public void onDestroyActionMode(ActionMode mode) {
                unhighlightResult();
                mActionMode = null;
            }

            @Override
            public void onGetContentRect(ActionMode mode, View view, Rect outRect) {
                super.onGetContentRect(mode, view, outRect);

                outRect.left += view.getPaddingLeft();
                outRect.top += view.getPaddingTop();
                outRect.right -= view.getPaddingRight();
                outRect.bottom -= view.getPaddingBottom();
                final int width = (int) Layout.getDesiredWidth(getText(), getPaint());
                if (width < outRect.width()) {
                    outRect.left = outRect.right - width;
                }

                if (!BuildCompat.isAtLeastN()) {
                    // The CAB (prior to N) only takes the translation of a view into account, so
                    // if a scale is applied to the view then the offset outRect will end up being
                    // positioned incorrectly. We workaround that limitation by manually applying
                    // the scale to the outRect, which the CAB will then offset to the correct
                    // position.
                    final float scaleX = view.getScaleX();
                    final float scaleY = view.getScaleY();
                    outRect.left *= scaleX;
                    outRect.right *= scaleX;
                    outRect.top *= scaleY;
                    outRect.bottom *= scaleY;
                }
            }
        };
        setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if (mValid) {
                    mActionMode = startActionMode(mCopyActionModeCallback,
                            ActionMode.TYPE_FLOATING);
                    return true;
                }
                return false;
            }
        });
    }

    /**
     * Use ContextMenu for copy/memory support on L and lower.
     */
    private void setupContextMenu() {
        setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
            @Override
            public void onCreateContextMenu(ContextMenu contextMenu, View view,
                    ContextMenu.ContextMenuInfo contextMenuInfo) {
                final MenuInflater inflater = new MenuInflater(getContext());
                createContextMenu(inflater, contextMenu);
                mContextMenu = contextMenu;
                for (int i = 0; i < contextMenu.size(); i ++) {
                    contextMenu.getItem(i).setOnMenuItemClickListener(CalculatorResult.this);
                }
            }
        });
        setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if (mValid) {
                    return showContextMenu();
                }
                return false;
            }
        });
    }

    private boolean createContextMenu(MenuInflater inflater, Menu menu) {
        inflater.inflate(R.menu.menu_result, menu);
        final boolean displayMemory = mEvaluator.getMemoryIndex() != 0;
        final MenuItem memoryAddItem = menu.findItem(R.id.memory_add);
        final MenuItem memorySubtractItem = menu.findItem(R.id.memory_subtract);
        memoryAddItem.setEnabled(displayMemory);
        memorySubtractItem.setEnabled(displayMemory);
        highlightResult();
        return true;
    }

    public boolean stopActionModeOrContextMenu() {
        if (mActionMode != null) {
            mActionMode.finish();
            return true;
        }
        if (mContextMenu != null) {
            unhighlightResult();
            mContextMenu.close();
            return true;
        }
        return false;
    }

    private void highlightResult() {
        final Spannable text = (Spannable) getText();
        text.setSpan(mHighlightSpan, 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    }

    private void unhighlightResult() {
        final Spannable text = (Spannable) getText();
        text.removeSpan(mHighlightSpan);
    }

    private void setPrimaryClip(ClipData clip) {
        ClipboardManager clipboard = (ClipboardManager) getContext().
                                               getSystemService(Context.CLIPBOARD_SERVICE);
        clipboard.setPrimaryClip(clip);
    }

    private void copyContent() {
        final CharSequence text = getFullCopyText();
        ClipboardManager clipboard =
                (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
        // We include a tag URI, to allow us to recognize our own results and handle them
        // specially.
        ClipData.Item newItem = new ClipData.Item(text, null, mEvaluator.capture(mIndex));
        String[] mimeTypes = new String[] {ClipDescription.MIMETYPE_TEXT_PLAIN};
        ClipData cd = new ClipData("calculator result", mimeTypes, newItem);
        clipboard.setPrimaryClip(cd);
        Toast.makeText(getContext(), R.string.text_copied_toast, Toast.LENGTH_SHORT).show();
    }

    @Override
    public boolean onMenuItemClick(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.memory_add:
                onMemoryAdd();
                return true;
            case R.id.memory_subtract:
                onMemorySubtract();
                return true;
            case R.id.memory_store:
                onMemoryStore();
                return true;
            case R.id.menu_copy:
                if (mEvaluator.evaluationInProgress(mIndex)) {
                    // Refuse to copy placeholder characters.
                    return false;
                } else {
                    copyContent();
                    unhighlightResult();
                    return true;
                }
            default:
                return false;
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        stopActionModeOrContextMenu();
        super.onDetachedFromWindow();
    }
}
