package com.kfzs.android.view.widget;

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.drawable.Drawable;
import android.os.Build;
import android.text.Editable;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

import com.kfzs.android.view.R;

/**
 * <pre>
 *     sinlov
 *
 *     /\__/\
 *    /`    '\
 *  ≈≈≈ 0  0 ≈≈≈ Hello world!
 *    \  --  /
 *   /        \
 *  /          \
 * |            |
 *  \  ||  ||  /
 *   \_oo__oo_/≡≡≡≡≡≡≡≡o
 *
 * </pre>
 * Created by sinlov on 17/2/27.
 */
public class MDLEditText extends android.support.v7.widget.AppCompatAutoCompleteTextView {
    // 画下划线的画笔
    private Paint paint;
    // 下划线的开始y坐标
    private int lineStartY;
    // 下划线的初始颜色
    private int preLineColor;

    // 额外的顶部内边距
    private int extraTopPadding;
    // 额外的底部内边距
    private int extraBottomPadding;

    // 绘制标签的画笔
    private TextPaint textPaint;
    // 标签的透明度
    private float textAlpha = 0;
    // 标签的颜色
    private int labelColor;
    // 标签的文字内容
    private String labelText;
    // 超过限制长度时的下划线颜色
    private int overLengthColor;
    // 最大输入的字符数
    private int maxCount;
    // 当前输入的字符数
    private int presentCount;
    // 标签文字的动画
    ValueAnimator labelAnim;
    // 标签是否展现的标志
    private boolean isShow = false;
    // 右侧展现删除按钮标志 默认 false
    private boolean isWithClearButtonRight;

    // 右侧删除按钮
    private Drawable mClearDrawable;

    // 标签动画中标签移动的比例
    private float yFraction;
    // 用来获取计数结果的字符串
    private StringBuffer countString;
    // 绘制计数结果的画笔
    private TextPaint countPaint;


    public MDLEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs); // 初始化
    }

    public MDLEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs); // 初始化
    }

    // 初始化各个数据
    private void init(AttributeSet attrs) {
        if (attrs != null) {
            TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.MDLEditText);
            // 获取设置的最大输入字符数，默认为-1，-1时不限制输入
            maxCount = array.getInteger(R.styleable.MDLEditText_maxLength, -1);
            // 捕捉焦点后，下划线的初始颜色
            preLineColor = array.getColor(R.styleable.MDLEditText_preLineColor, 0xee18b4ed);
            // 标签文字的颜色
            labelColor = array.getColor(R.styleable.MDLEditText_labelColor, 0xff18b4ed);
            // 标签文字的内容
            labelText = array.getString(R.styleable.MDLEditText_labelText);
            if (labelText == null)
                labelText = "";
            // 超过长度后的下划线颜色
            overLengthColor = array.getColor(R.styleable.MDLEditText_overLengthColor, Color.RED);

            isWithClearButtonRight = array.getBoolean(R.styleable.MDLEditText_withClearButtonRight, false);
            Drawable clearButtonRightDrawable = array.getDrawable(R.styleable.MDLEditText_clearButtonRightDrawable);

            array.recycle();

            // 用来存放右下角的计数内容的字符串
            countString = new StringBuffer();

            // 初始化下划线画笔
            paint = new Paint();
            paint.setColor(Color.LTGRAY);
            paint.setAntiAlias(true);
            paint.setStrokeWidth(dp2Pix(0.35f));
            paint.setStyle(Paint.Style.FILL_AND_STROKE);
            paint.setStrokeCap(Paint.Cap.ROUND);

            // 初始化标签画笔
            textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
            textPaint.setTextSize(sp2Pix(14.5f));
            textPaint.setColor(labelColor);

            // 初始化字符计数的画笔
            countPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
            countPaint.setTextSize(sp2Pix(14.5f));
            countPaint.setColor(Color.LTGRAY);

            // 获取额外的顶部内边距
            extraTopPadding = (int) getTextHeight(textPaint) + dp2Pix(4);

            // 获取额外的底部内布距
            extraBottomPadding = (int) getTextHeight(textPaint) + dp2Pix(6);

            // 矫正EditText的内边距
            correctPadding();

            // 初始化标签动画
            labelAnim = ValueAnimator.ofFloat(0, 255);
            labelAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    // 获取标签的透明度
                    textAlpha = (float) animation.getAnimatedValue();
                    // 获取文字的高度比例：
                    // 当透明度为0时，高度比例为1.5，为1时，高度为1
                    // 达到一种从底部浮现的效果
                    yFraction = (float) (-(5.0f / 2550.0f) * textAlpha + 1.5);
                    // 重绘
                    invalidate();
                }
            });

            if (isWithClearButtonRight) {
                mClearDrawable = getCompoundDrawables()[2];//获取输入框右侧drawable
                if (mClearDrawable == null) {
                    if (clearButtonRightDrawable != null) {
                        mClearDrawable = clearButtonRightDrawable;
                    } else {
                        mClearDrawable = getResources().getDrawable(android.R.drawable.ic_delete);
                    }
                }
                mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight());
                setClearDrawableVisible(false);
            }

            // 初始化监听器
            initListener();
            // 设置提示字体颜色
            setHintTextColor(Color.LTGRAY);
            // 设置文字方向
            setGravity(SCROLL_INDICATOR_LEFT);
        }
    }

    /**
     * EditText内容改变监听器
     */
    private void initListener() {
        addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                if (isWithClearButtonRight) {
                    setClearDrawableVisible(getText().length() > 0);
                }

                // 当内容改变后，计数、并判断是否超过规定字符长度
                if (maxCount != -1) {
                    // 添加计数字符串
                    countString.delete(0, countString.length());
                    presentCount = s.length();
                    countString.append(presentCount);
                    countString.append(" / ");
                    countString.append(maxCount);

                    // 超过规定长度时，绘制的颜色发生变化
                    if (presentCount > maxCount) {
                        paint.setColor(overLengthColor);
                        countPaint.setColor(overLengthColor);
                    } else {
                        paint.setColor(preLineColor);
                        countPaint.setColor(Color.LTGRAY);
                    }
                }

                // 当内容长度为0并获得焦点时：
                if (s.length() == 0 && isShow && isFocused()) {
                    // 将标签动画逆序播放，将标签隐藏
                    labelAnim.reverse();
                    isShow = false;

                } else if (s.length() != 0 && !isShow && isFocused()) {
                    // 当内容长度不为0时，播放标签浮出一次
                    labelAnim.start();
                    isShow = true;

                }
            }
        });

        // 添加焦点的获取通知
        setOnFocusChangeListener(new OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                // 获取焦点时
                if (hasFocus) {
                    if (isWithClearButtonRight) {
                        setClearDrawableVisible(getText().length() > 0);
                    }
                    // 改变下划线的粗细
                    paint.setStrokeWidth(dp2Pix(1.3f));
                    // 改变标签的颜色
                    textPaint.setColor(labelColor);

                    if (presentCount > maxCount && maxCount != -1) {
                        // 超出字符长度时，设置画笔颜色
                        paint.setColor(overLengthColor);
                        countPaint.setColor(overLengthColor);
                    } else {
                        // 不超出字符长度/不设置规定长度时，设置画笔颜色
                        paint.setColor(preLineColor);
                        countPaint.setColor(Color.LTGRAY);
                    }

                } else {
                    if (isWithClearButtonRight) {
                        setClearDrawableVisible(false);
                    }
                    // 没有获取焦点时，改变下划线的颜色和粗细和标签颜色
                    textPaint.setColor(Color.LTGRAY);
                    paint.setColor(Color.LTGRAY);
                    paint.setStrokeWidth(dp2Pix(0.35f));
                }

            }
        });
        setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_UP:
//                        当手指抬起的位置在clean的图标的区域
//                        我们将此视为进行清除操作
//                        getWidth():得到控件的宽度
//                        event.getX():抬起时的坐标(改坐标是相对于控件本身而言的)
//                        getTotalPaddingRight():clean的图标左边缘至控件右边缘的距离
//                        getPaddingRight():clean的图标右边缘至控件右边缘的距离
//                        getWidth() - getTotalPaddingRight()表示:
//                        控件左边到clean的图标左边缘的区域
//                        getWidth() - getPaddingRight()表示:
//                        控件左边到clean的图标右边缘的区域
//                        所以这两者之间的区域刚好是clean的图标的区域
                        if (isWithClearButtonRight) {
                            boolean isClean = (event.getX() > (getWidth() - getTotalPaddingRight())) &&
                                    (event.getX() < (getWidth() - getPaddingRight()));
                            if (isClean) {
                                setText("");
                            }
                        }
                        break;
                    default:
                        break;
                }
                return false;
            }
        });
    }


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        // 设置EditText的背景为空，主要为了隐藏自带的下划线
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            setBackground(null);
        } else {
            setBackgroundDrawable(null);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // 获取下划线的起点高度
        lineStartY = getScrollY() + getHeight() - getPaddingBottom() + dp2Pix(5);
        // 设置标签的透明度
        textPaint.setAlpha((int) textAlpha);
        // 根据标签的高度比例绘制标签文字
        canvas.drawText(labelText, getScrollX(), (getScrollY() - dp2Pix(4) + extraTopPadding) * yFraction, textPaint);
        // 绘制下划线
        canvas.drawRect(getScrollX(), lineStartY, getScrollX() + getWidth() - getPaddingRight(), lineStartY + dp2Pix(0.8f), paint);
        // 根据是否有字符长度规定绘制右下角的计数
        if (maxCount != -1) {
            canvas.drawText(countString.toString(), getScrollX() + getWidth() - getPaddingRight() - getTextWidth(countString.toString(), countPaint), lineStartY + extraBottomPadding, countPaint);
        }
        // 开始EditText原生的绘制
        super.onDraw(canvas);
    }

    @Override
    public void setText(CharSequence text, BufferType type) {
        super.setText(text, type);
        //防止监听不到置空消息
        if (TextUtils.isEmpty(text) && labelAnim != null && isShow) {
            labelAnim.reverse();
            isShow = false;
        }
    }

    /**
     * 获取文字的高度
     *
     * @param paint {@link TextPaint}
     * @return height
     */
    private float getTextHeight(Paint paint) {
        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        return fontMetrics.bottom - fontMetrics.descent - fontMetrics.ascent;
    }


    /**
     * 获取文字的宽度
     *
     * @param text  {@link String}
     * @param paint {@link TextPaint}
     * @return length of this text
     */
    private int getTextWidth(String text, TextPaint paint) {
        return (int) paint.measureText(text);
    }

    private float sp2Pix(float i) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, i, getContext().getResources().getDisplayMetrics());
    }

    private int dp2Pix(float i) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, i, getContext().getResources().getDisplayMetrics());
    }


    /**
     * 需要绘制标签和下划线，因此需要重新设置padding值
     */
    private void correctPadding() {
        super.setPadding(getPaddingLeft(), getPaddingTop() + extraTopPadding, getPaddingRight(), getPaddingBottom() + extraBottomPadding + dp2Pix(5));
    }

    /**
     * visible clear drawable
     *
     * @param isVisible isVisible
     */
    private void setClearDrawableVisible(boolean isVisible) {
        Drawable mRightDrawable;
        if (isVisible) {
            mRightDrawable = this.mClearDrawable;
        } else {
            mRightDrawable = null;
        }
        setCompoundDrawables(getCompoundDrawables()[0], getCompoundDrawables()[1], mRightDrawable, getCompoundDrawables()[3]);
    }
}
