package com.atominvention.materialize.ui;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.NinePatchDrawable;
import android.util.AttributeSet;
import android.widget.EditText;

import com.atominvention.materialize.R;

/**
 * Created by AtomInvention on 15/9/14.
 */
public class MaterialEditText extends EditText {

    private int mControlNormalColor;
    private int mActiveTintColor;
    private float mDisabledAlpha;
    private NinePatchDrawable mActivitedControlDrawable;
    private float mFocusAniRatio;
    private int mWidth;
    private int mHeight;

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

    public MaterialEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs);
    }

    public MaterialEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(attrs);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        if (changed) {
            mActivitedControlDrawable = (NinePatchDrawable) getResources()
                    .getDrawable(R.drawable.textfield_activated_mtrl_alpha);
            mActivitedControlDrawable.setBounds(0, 0, getWidth(), getHeight());
            mActivitedControlDrawable.setColorFilter(getTintColor(true), PorterDuff.Mode.SRC_IN);
        }
        mWidth = getWidth();
        mHeight = getHeight();
    }

    @Override
    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect);
        if (isEnabled()) {
            tintControl(focused);
            animateFocus(focused);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (isFocused() && isEnabled()) {
            canvas.save();
            canvas.clipRect(mWidth * 0.5f * (1 - mFocusAniRatio), 0, mWidth * 0.5f * (1 + mFocusAniRatio), mHeight);
            mActivitedControlDrawable.draw(canvas);
            canvas.restore();
        }
    }

    @Override
    public void setEnabled(boolean enabled) {
        super.setEnabled(enabled);
        setAlpha(enabled ? 1.0f : mDisabledAlpha);
    }

    private void init(AttributeSet attrs) {
        getAttrs(attrs);
        tintControl(false);
        if (!isEnabled()) {
            setAlpha(mDisabledAlpha);
        }
    }

    private void getAttrs(AttributeSet attrs) {
        if (attrs == null) {
            return;
        }
        TypedArray typedArray = getContext().obtainStyledAttributes(attrs,
                new int[]{R.attr.normal_control_color,
                        android.R.attr.disabledAlpha,
                        R.attr.active_tint_color,
                        R.attr.color_accent});
        mControlNormalColor = typedArray.getColor(0,
                getResources().getColor(R.color.material_control_normal_dark));
        mDisabledAlpha = typedArray.getFloat(1, 0.0f);
        int colorAccent = typedArray.getColor(3, getResources().getColor(R.color.default_color_accent));
        mActiveTintColor = typedArray.getColor(2, colorAccent);
    }

    private void tintControl(boolean focused) {
        getBackground().setColorFilter(getTintColor(focused), PorterDuff.Mode.SRC_IN);
    }

    private int getTintColor(boolean focused) {
        return focused ? mActiveTintColor : mControlNormalColor;
    }

    private void animateFocus(final boolean focused) {
        ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mFocusAniRatio = (Float) animation.getAnimatedValue();
                getBackground().setColorFilter(
                        blendColors(getTintColor(focused), getTintColor(!focused), mFocusAniRatio),
                                PorterDuff.Mode.SRC_IN);
            }
        });

        anim.start();
    }

    private static int blendColors(int color1, int color2, float ratio) {
        final float inverseRation = 1f - ratio;
        float a = (Color.alpha(color1) * ratio) + (Color.alpha(color2) * inverseRation);
        float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation);
        float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation);
        float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation);
        return Color.argb((int) a, (int) r, (int) g, (int) b);
    }

}
