/*
 * Copyright (C) 2014 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.keyguard;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.os.PowerManager;
import android.os.SystemClock;
import android.provider.Settings;
import android.text.InputType;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.EditText;

import com.android.systemui.R;

import java.util.ArrayList;
import java.util.Stack;

/**
 * A View similar to a textView which contains password text and can animate when the text is
 * changed
 */
public class PasswordTextView extends View {

    private static final float DOT_OVERSHOOT_FACTOR = 1.5f;
    private static final long DOT_APPEAR_DURATION_OVERSHOOT = 320;
    private static final long APPEAR_DURATION = 160;
    private static final long DISAPPEAR_DURATION = 160;
    private static final long RESET_DELAY_PER_ELEMENT = 40;
    private static final long RESET_MAX_DELAY = 200;

    /**
     * The overlap between the text disappearing and the dot appearing animation
     */
    private static final long DOT_APPEAR_TEXT_DISAPPEAR_OVERLAP_DURATION = 130;

    /**
     * The duration the text needs to stay there at least before it can morph into a dot
     */
    private static final long TEXT_REST_DURATION_AFTER_APPEAR = 100;

    /**
     * The duration the text should be visible, starting with the appear animation
     */
    private static final long TEXT_VISIBILITY_DURATION = 1300;

    /**
     * The position in time from [0,1] where the overshoot should be finished and the settle back
     * animation of the dot should start
     */
    private static final float OVERSHOOT_TIME_POSITION = 0.5f;

    private static char DOT = '\u2022';

    /**
     * The raw text size, will be multiplied by the scaled density when drawn
     */
    private final int mTextHeightRaw;
    private final int mGravity;
    private ArrayList<CharState> mTextChars = new ArrayList<>();
    private String mText = "";
    private Stack<CharState> mCharPool = new Stack<>();
    private int mDotSize;
    private PowerManager mPM;
    private int mCharPadding;
    private final Paint mDrawPaint = new Paint();
    private Interpolator mAppearInterpolator;
    private Interpolator mDisappearInterpolator;
    private Interpolator mFastOutSlowInInterpolator;
    private boolean mShowPassword;
    private UserActivityListener mUserActivityListener;

    public interface UserActivityListener {
        void onUserActivity();
    }

    public PasswordTextView(Context context) {
        this(context, null);
    }

    public PasswordTextView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public PasswordTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public PasswordTextView(Context context, AttributeSet attrs, int defStyleAttr,
            int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        setFocusableInTouchMode(true);
        setFocusable(true);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PasswordTextView);
        try {
            mTextHeightRaw = a.getInt(R.styleable.PasswordTextView_scaledTextSize, 0);
            mGravity = a.getInt(R.styleable.PasswordTextView_android_gravity, Gravity.CENTER);
            mDotSize = a.getDimensionPixelSize(R.styleable.PasswordTextView_dotSize,
                    getContext().getResources().getDimensionPixelSize(R.dimen.password_dot_size));
            mCharPadding = a.getDimensionPixelSize(R.styleable.PasswordTextView_charPadding,
                    getContext().getResources().getDimensionPixelSize(
                            R.dimen.password_char_padding));
            int textColor = a.getColor(R.styleable.PasswordTextView_android_textColor, Color.WHITE);
            mDrawPaint.setColor(textColor);
        } finally {
            a.recycle();
        }
        mDrawPaint.setFlags(Paint.SUBPIXEL_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);
        mDrawPaint.setTextAlign(Paint.Align.CENTER);
        mDrawPaint.setTypeface(Typeface.create(
                context.getString(com.android.internal.R.string.config_headlineFontFamily),
                0));
        mShowPassword = Settings.System.getInt(mContext.getContentResolver(),
                Settings.System.TEXT_SHOW_PASSWORD, 1) == 1;
        mAppearInterpolator = AnimationUtils.loadInterpolator(mContext,
                android.R.interpolator.linear_out_slow_in);
        mDisappearInterpolator = AnimationUtils.loadInterpolator(mContext,
                android.R.interpolator.fast_out_linear_in);
        mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(mContext,
                android.R.interpolator.fast_out_slow_in);
        mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        float totalDrawingWidth = getDrawingWidth();
        float currentDrawPosition;
        if ((mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.LEFT) {
            if ((mGravity & Gravity.RELATIVE_LAYOUT_DIRECTION) != 0
                    && getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
                currentDrawPosition = getWidth() - getPaddingRight() - totalDrawingWidth;
            } else {
                currentDrawPosition = getPaddingLeft();
            }
        } else {
            currentDrawPosition = getWidth() / 2 - totalDrawingWidth / 2;
        }
        int length = mTextChars.size();
        Rect bounds = getCharBounds();
        int charHeight = (bounds.bottom - bounds.top);
        float yPosition =
                (getHeight() - getPaddingBottom() - getPaddingTop()) / 2 + getPaddingTop();
        canvas.clipRect(getPaddingLeft(), getPaddingTop(),
                getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
        float charLength = bounds.right - bounds.left;
        for (int i = 0; i < length; i++) {
            CharState charState = mTextChars.get(i);
            float charWidth = charState.draw(canvas, currentDrawPosition, charHeight, yPosition,
                    charLength);
            currentDrawPosition += charWidth;
        }
    }

    @Override
    public boolean hasOverlappingRendering() {
        return false;
    }

    private Rect getCharBounds() {
        float textHeight = mTextHeightRaw * getResources().getDisplayMetrics().scaledDensity;
        mDrawPaint.setTextSize(textHeight);
        Rect bounds = new Rect();
        mDrawPaint.getTextBounds("0", 0, 1, bounds);
        return bounds;
    }

    private float getDrawingWidth() {
        int width = 0;
        int length = mTextChars.size();
        Rect bounds = getCharBounds();
        int charLength = bounds.right - bounds.left;
        for (int i = 0; i < length; i++) {
            CharState charState = mTextChars.get(i);
            if (i != 0) {
                width += mCharPadding * charState.currentWidthFactor;
            }
            width += charLength * charState.currentWidthFactor;
        }
        return width;
    }


    public void append(char c) {
        int visibleChars = mTextChars.size();
        CharSequence textbefore = getTransformedText();
        mText = mText + c;
        int newLength = mText.length();
        CharState charState;
        if (newLength > visibleChars) {
            charState = obtainCharState(c);
            mTextChars.add(charState);
        } else {
            charState = mTextChars.get(newLength - 1);
            charState.whichChar = c;
        }
        charState.startAppearAnimation();

        // ensure that the previous element is being swapped
        if (newLength > 1) {
            CharState previousState = mTextChars.get(newLength - 2);
            if (previousState.isDotSwapPending) {
                previousState.swapToDotWhenAppearFinished();
            }
        }
        userActivity();
        sendAccessibilityEventTypeViewTextChanged(textbefore, textbefore.length(), 0, 1);
    }

    public void setUserActivityListener(UserActivityListener userActivitiListener) {
        mUserActivityListener = userActivitiListener;
    }

    private void userActivity() {
        mPM.userActivity(SystemClock.uptimeMillis(), false);
        if (mUserActivityListener != null) {
            mUserActivityListener.onUserActivity();
        }
    }

    public void deleteLastChar() {
        int length = mText.length();
        CharSequence textbefore = getTransformedText();
        if (length > 0) {
            mText = mText.substring(0, length - 1);
            CharState charState = mTextChars.get(length - 1);
            charState.startRemoveAnimation(0, 0);
            sendAccessibilityEventTypeViewTextChanged(textbefore, textbefore.length() - 1, 1, 0);
        }
        userActivity();
    }

    public String getText() {
        return mText;
    }

    private CharSequence getTransformedText() {
        int textLength = mTextChars.size();
        StringBuilder stringBuilder = new StringBuilder(textLength);
        for (int i = 0; i < textLength; i++) {
            CharState charState = mTextChars.get(i);
            // If the dot is disappearing, the character is disappearing entirely. Consider
            // it gone.
            if (charState.dotAnimator != null && !charState.dotAnimationIsGrowing) {
                continue;
            }
            stringBuilder.append(charState.isCharVisibleForA11y() ? charState.whichChar : DOT);
        }
        return stringBuilder;
    }

    private CharState obtainCharState(char c) {
        CharState charState;
        if(mCharPool.isEmpty()) {
            charState = new CharState();
        } else {
            charState = mCharPool.pop();
            charState.reset();
        }
        charState.whichChar = c;
        return charState;
    }

    public void reset(boolean animated, boolean announce) {
        CharSequence textbefore = getTransformedText();
        mText = "";
        int length = mTextChars.size();
        int middleIndex = (length - 1) / 2;
        long delayPerElement = RESET_DELAY_PER_ELEMENT;
        for (int i = 0; i < length; i++) {
            CharState charState = mTextChars.get(i);
            if (animated) {
                int delayIndex;
                if (i <= middleIndex) {
                    delayIndex = i * 2;
                } else {
                    int distToMiddle = i - middleIndex;
                    delayIndex = (length - 1) - (distToMiddle - 1) * 2;
                }
                long startDelay = delayIndex * delayPerElement;
                startDelay = Math.min(startDelay, RESET_MAX_DELAY);
                long maxDelay = delayPerElement * (length - 1);
                maxDelay = Math.min(maxDelay, RESET_MAX_DELAY) + DISAPPEAR_DURATION;
                charState.startRemoveAnimation(startDelay, maxDelay);
                charState.removeDotSwapCallbacks();
            } else {
                mCharPool.push(charState);
            }
        }
        if (!animated) {
            mTextChars.clear();
        }
        if (announce) {
            sendAccessibilityEventTypeViewTextChanged(textbefore, 0, textbefore.length(), 0);
        }
    }

    void sendAccessibilityEventTypeViewTextChanged(CharSequence beforeText, int fromIndex,
                                                   int removedCount, int addedCount) {
        if (AccessibilityManager.getInstance(mContext).isEnabled() &&
                (isFocused() || isSelected() && isShown())) {
            AccessibilityEvent event =
                    AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
            event.setFromIndex(fromIndex);
            event.setRemovedCount(removedCount);
            event.setAddedCount(addedCount);
            event.setBeforeText(beforeText);
            CharSequence transformedText = getTransformedText();
            if (!TextUtils.isEmpty(transformedText)) {
                event.getText().add(transformedText);
            }
            event.setPassword(true);
            sendAccessibilityEventUnchecked(event);
        }
    }

    @Override
    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
        super.onInitializeAccessibilityEvent(event);

        event.setClassName(EditText.class.getName());
        event.setPassword(true);
    }

    @Override
    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
        super.onInitializeAccessibilityNodeInfo(info);

        info.setClassName(EditText.class.getName());
        info.setPassword(true);
        info.setText(getTransformedText());

        info.setEditable(true);

        info.setInputType(InputType.TYPE_NUMBER_VARIATION_PASSWORD);
    }

    private class CharState {
        char whichChar;
        ValueAnimator textAnimator;
        boolean textAnimationIsGrowing;
        Animator dotAnimator;
        boolean dotAnimationIsGrowing;
        ValueAnimator widthAnimator;
        boolean widthAnimationIsGrowing;
        float currentTextSizeFactor;
        float currentDotSizeFactor;
        float currentWidthFactor;
        boolean isDotSwapPending;
        float currentTextTranslationY = 1.0f;
        ValueAnimator textTranslateAnimator;

        Animator.AnimatorListener removeEndListener = new AnimatorListenerAdapter() {
            private boolean mCancelled;
            @Override
            public void onAnimationCancel(Animator animation) {
                mCancelled = true;
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                if (!mCancelled) {
                    mTextChars.remove(CharState.this);
                    mCharPool.push(CharState.this);
                    reset();
                    cancelAnimator(textTranslateAnimator);
                    textTranslateAnimator = null;
                }
            }

            @Override
            public void onAnimationStart(Animator animation) {
                mCancelled = false;
            }
        };

        Animator.AnimatorListener dotFinishListener = new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                dotAnimator = null;
            }
        };

        Animator.AnimatorListener textFinishListener = new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                textAnimator = null;
            }
        };

        Animator.AnimatorListener textTranslateFinishListener = new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                textTranslateAnimator = null;
            }
        };

        Animator.AnimatorListener widthFinishListener = new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                widthAnimator = null;
            }
        };

        private ValueAnimator.AnimatorUpdateListener dotSizeUpdater
                = new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                currentDotSizeFactor = (float) animation.getAnimatedValue();
                invalidate();
            }
        };

        private ValueAnimator.AnimatorUpdateListener textSizeUpdater
                = new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                boolean textVisibleBefore = isCharVisibleForA11y();
                float beforeTextSizeFactor = currentTextSizeFactor;
                currentTextSizeFactor = (float) animation.getAnimatedValue();
                if (textVisibleBefore != isCharVisibleForA11y()) {
                    currentTextSizeFactor = beforeTextSizeFactor;
                    CharSequence beforeText = getTransformedText();
                    currentTextSizeFactor = (float) animation.getAnimatedValue();
                    int indexOfThisChar = mTextChars.indexOf(CharState.this);
                    if (indexOfThisChar >= 0) {
                        sendAccessibilityEventTypeViewTextChanged(
                                beforeText, indexOfThisChar, 1, 1);
                    }
                }
                invalidate();
            }
        };

        private ValueAnimator.AnimatorUpdateListener textTranslationUpdater
                = new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                currentTextTranslationY = (float) animation.getAnimatedValue();
                invalidate();
            }
        };

        private ValueAnimator.AnimatorUpdateListener widthUpdater
                = new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                currentWidthFactor = (float) animation.getAnimatedValue();
                invalidate();
            }
        };

        private Runnable dotSwapperRunnable = new Runnable() {
            @Override
            public void run() {
                performSwap();
                isDotSwapPending = false;
            }
        };

        void reset() {
            whichChar = 0;
            currentTextSizeFactor = 0.0f;
            currentDotSizeFactor = 0.0f;
            currentWidthFactor = 0.0f;
            cancelAnimator(textAnimator);
            textAnimator = null;
            cancelAnimator(dotAnimator);
            dotAnimator = null;
            cancelAnimator(widthAnimator);
            widthAnimator = null;
            currentTextTranslationY = 1.0f;
            removeDotSwapCallbacks();
        }

        void startRemoveAnimation(long startDelay, long widthDelay) {
            boolean dotNeedsAnimation = (currentDotSizeFactor > 0.0f && dotAnimator == null)
                    || (dotAnimator != null && dotAnimationIsGrowing);
            boolean textNeedsAnimation = (currentTextSizeFactor > 0.0f && textAnimator == null)
                    || (textAnimator != null && textAnimationIsGrowing);
            boolean widthNeedsAnimation = (currentWidthFactor > 0.0f && widthAnimator == null)
                    || (widthAnimator != null && widthAnimationIsGrowing);
            if (dotNeedsAnimation) {
                startDotDisappearAnimation(startDelay);
            }
            if (textNeedsAnimation) {
                startTextDisappearAnimation(startDelay);
            }
            if (widthNeedsAnimation) {
                startWidthDisappearAnimation(widthDelay);
            }
        }

        void startAppearAnimation() {
            boolean dotNeedsAnimation = !mShowPassword
                    && (dotAnimator == null || !dotAnimationIsGrowing);
            boolean textNeedsAnimation = mShowPassword
                    && (textAnimator == null || !textAnimationIsGrowing);
            boolean widthNeedsAnimation = (widthAnimator == null || !widthAnimationIsGrowing);
            if (dotNeedsAnimation) {
                startDotAppearAnimation(0);
            }
            if (textNeedsAnimation) {
                startTextAppearAnimation();
            }
            if (widthNeedsAnimation) {
                startWidthAppearAnimation();
            }
            if (mShowPassword) {
                postDotSwap(TEXT_VISIBILITY_DURATION);
            }
        }

        /**
         * Posts a runnable which ensures that the text will be replaced by a dot after {@link
         * com.android.keyguard.PasswordTextView#TEXT_VISIBILITY_DURATION}.
         */
        private void postDotSwap(long delay) {
            removeDotSwapCallbacks();
            postDelayed(dotSwapperRunnable, delay);
            isDotSwapPending = true;
        }

        private void removeDotSwapCallbacks() {
            removeCallbacks(dotSwapperRunnable);
            isDotSwapPending = false;
        }

        void swapToDotWhenAppearFinished() {
            removeDotSwapCallbacks();
            if (textAnimator != null) {
                long remainingDuration = textAnimator.getDuration()
                        - textAnimator.getCurrentPlayTime();
                postDotSwap(remainingDuration + TEXT_REST_DURATION_AFTER_APPEAR);
            } else {
                performSwap();
            }
        }

        private void performSwap() {
            startTextDisappearAnimation(0);
            startDotAppearAnimation(DISAPPEAR_DURATION
                    - DOT_APPEAR_TEXT_DISAPPEAR_OVERLAP_DURATION);
        }

        private void startWidthDisappearAnimation(long widthDelay) {
            cancelAnimator(widthAnimator);
            widthAnimator = ValueAnimator.ofFloat(currentWidthFactor, 0.0f);
            widthAnimator.addUpdateListener(widthUpdater);
            widthAnimator.addListener(widthFinishListener);
            widthAnimator.addListener(removeEndListener);
            widthAnimator.setDuration((long) (DISAPPEAR_DURATION * currentWidthFactor));
            widthAnimator.setStartDelay(widthDelay);
            widthAnimator.start();
            widthAnimationIsGrowing = false;
        }

        private void startTextDisappearAnimation(long startDelay) {
            cancelAnimator(textAnimator);
            textAnimator = ValueAnimator.ofFloat(currentTextSizeFactor, 0.0f);
            textAnimator.addUpdateListener(textSizeUpdater);
            textAnimator.addListener(textFinishListener);
            textAnimator.setInterpolator(mDisappearInterpolator);
            textAnimator.setDuration((long) (DISAPPEAR_DURATION * currentTextSizeFactor));
            textAnimator.setStartDelay(startDelay);
            textAnimator.start();
            textAnimationIsGrowing = false;
        }

        private void startDotDisappearAnimation(long startDelay) {
            cancelAnimator(dotAnimator);
            ValueAnimator animator = ValueAnimator.ofFloat(currentDotSizeFactor, 0.0f);
            animator.addUpdateListener(dotSizeUpdater);
            animator.addListener(dotFinishListener);
            animator.setInterpolator(mDisappearInterpolator);
            long duration = (long) (DISAPPEAR_DURATION * Math.min(currentDotSizeFactor, 1.0f));
            animator.setDuration(duration);
            animator.setStartDelay(startDelay);
            animator.start();
            dotAnimator = animator;
            dotAnimationIsGrowing = false;
        }

        private void startWidthAppearAnimation() {
            cancelAnimator(widthAnimator);
            widthAnimator = ValueAnimator.ofFloat(currentWidthFactor, 1.0f);
            widthAnimator.addUpdateListener(widthUpdater);
            widthAnimator.addListener(widthFinishListener);
            widthAnimator.setDuration((long) (APPEAR_DURATION * (1f - currentWidthFactor)));
            widthAnimator.start();
            widthAnimationIsGrowing = true;
        }

        private void startTextAppearAnimation() {
            cancelAnimator(textAnimator);
            textAnimator = ValueAnimator.ofFloat(currentTextSizeFactor, 1.0f);
            textAnimator.addUpdateListener(textSizeUpdater);
            textAnimator.addListener(textFinishListener);
            textAnimator.setInterpolator(mAppearInterpolator);
            textAnimator.setDuration((long) (APPEAR_DURATION * (1f - currentTextSizeFactor)));
            textAnimator.start();
            textAnimationIsGrowing = true;

            // handle translation
            if (textTranslateAnimator == null) {
                textTranslateAnimator = ValueAnimator.ofFloat(1.0f, 0.0f);
                textTranslateAnimator.addUpdateListener(textTranslationUpdater);
                textTranslateAnimator.addListener(textTranslateFinishListener);
                textTranslateAnimator.setInterpolator(mAppearInterpolator);
                textTranslateAnimator.setDuration(APPEAR_DURATION);
                textTranslateAnimator.start();
            }
        }

        private void startDotAppearAnimation(long delay) {
            cancelAnimator(dotAnimator);
            if (!mShowPassword) {
                // We perform an overshoot animation
                ValueAnimator overShootAnimator = ValueAnimator.ofFloat(currentDotSizeFactor,
                        DOT_OVERSHOOT_FACTOR);
                overShootAnimator.addUpdateListener(dotSizeUpdater);
                overShootAnimator.setInterpolator(mAppearInterpolator);
                long overShootDuration = (long) (DOT_APPEAR_DURATION_OVERSHOOT
                        * OVERSHOOT_TIME_POSITION);
                overShootAnimator.setDuration(overShootDuration);
                ValueAnimator settleBackAnimator = ValueAnimator.ofFloat(DOT_OVERSHOOT_FACTOR,
                        1.0f);
                settleBackAnimator.addUpdateListener(dotSizeUpdater);
                settleBackAnimator.setDuration(DOT_APPEAR_DURATION_OVERSHOOT - overShootDuration);
                settleBackAnimator.addListener(dotFinishListener);
                AnimatorSet animatorSet = new AnimatorSet();
                animatorSet.playSequentially(overShootAnimator, settleBackAnimator);
                animatorSet.setStartDelay(delay);
                animatorSet.start();
                dotAnimator = animatorSet;
            } else {
                ValueAnimator growAnimator = ValueAnimator.ofFloat(currentDotSizeFactor, 1.0f);
                growAnimator.addUpdateListener(dotSizeUpdater);
                growAnimator.setDuration((long) (APPEAR_DURATION * (1.0f - currentDotSizeFactor)));
                growAnimator.addListener(dotFinishListener);
                growAnimator.setStartDelay(delay);
                growAnimator.start();
                dotAnimator = growAnimator;
            }
            dotAnimationIsGrowing = true;
        }

        private void cancelAnimator(Animator animator) {
            if (animator != null) {
                animator.cancel();
            }
        }

        /**
         * Draw this char to the canvas.
         *
         * @return The width this character contributes, including padding.
         */
        public float draw(Canvas canvas, float currentDrawPosition, int charHeight, float yPosition,
                float charLength) {
            boolean textVisible = currentTextSizeFactor > 0;
            boolean dotVisible = currentDotSizeFactor > 0;
            float charWidth = charLength * currentWidthFactor;
            if (textVisible) {
                float currYPosition = yPosition + charHeight / 2.0f * currentTextSizeFactor
                        + charHeight * currentTextTranslationY * 0.8f;
                canvas.save();
                float centerX = currentDrawPosition + charWidth / 2;
                canvas.translate(centerX, currYPosition);
                canvas.scale(currentTextSizeFactor, currentTextSizeFactor);
                canvas.drawText(Character.toString(whichChar), 0, 0, mDrawPaint);
                canvas.restore();
            }
            if (dotVisible) {
                canvas.save();
                float centerX = currentDrawPosition + charWidth / 2;
                canvas.translate(centerX, yPosition);
                canvas.drawCircle(0, 0, mDotSize / 2 * currentDotSizeFactor, mDrawPaint);
                canvas.restore();
            }
            return charWidth + mCharPadding * currentWidthFactor;
        }

        public boolean isCharVisibleForA11y() {
            // The text has size 0 when it is first added, but we want to count it as visible if
            // it will become visible presently. Count text as visible if an animator
            // is configured to make it grow.
            boolean textIsGrowing = textAnimator != null && textAnimationIsGrowing;
            return (currentTextSizeFactor > 0) || textIsGrowing;
        }
    }
}
