package com.hardwork.fg607.relaxfinger.view;

import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.ScaleAnimation;
import android.widget.LinearLayout;
import com.hardwork.fg607.relaxfinger.R;
import com.hardwork.fg607.relaxfinger.utils.DensityUtil;
import com.hardwork.fg607.relaxfinger.utils.FloatingBallUtils;
import com.hardwork.fg607.relaxfinger.utils.ImageUtils;

import net.grandcentrix.tray.AppPreferences;

/**
 * Created by fg607 on 16-11-24.
 */

public class BallView extends View {

    public static final String TAG = "BallView";
    public static final int MIN_BALL_ALPHA = 255;
    public static final int MAX_BALL_ALPHA = 10;
    public static final int MIN_BALL_SIZE = 105;
    public static final int MAX_BALL_SIZE = 210;

    public static final int FEED_ZOOM = 10;
    public static final int SINGLE_TAP = 0;
    public static final int DOUBLE_TAP = 1;
    public static final int LONGPRESS = 2;
    public static final int SWIPE_UP = 3;
    public static final int SWIPE_DOWN = 4;
    public static final int SWIPE_LEFT = 5;
    public static final int SWIPE_RIGHT= 6;
    public static final int MOVE = 7;
    public static final int DOWN = 8;
    public static final int QUICK_SINGLE_TAP = 9;
    public static final int MOVE_FINISH = 10;

    public static final int LONG_PRESS_TIMEOUT = 200;

    public static final int DOUBLE_TAP_TIMEOUT = 130;
    private static final int HOME_KEY_PRESSED = 11;
    private static final int RECENT_KEY_PRESSED = 12;
    private static final int SET_ALPHA = 13;
    private static final int FEEDBACK = 14;

    private Context mContext;
    private int mSize;
    private int mAlpha;
    private String mTheme;
    private boolean mCanMove = true;
    private boolean mHasScrolled = false;
    private boolean mHasMoved = false;
    private AppPreferences mPreferences;
    private WindowManager mWindowManager;
    private WindowManager.LayoutParams mWinLayoutParams;
    private LinearLayout mParentLayout;

    private ScaleAnimation mZoomInAnim;
    private ScaleAnimation mZoomOutAnim;

    private OnGestureListener mGestureListener;
    private OnBallEventListener mBallEventListener;

    private int mTouchSlop;
    private int mTouchSlopSquare;
    private int mDownX;
    private int mDownY;
    private boolean mIsDoubleTapping;
    private boolean mGestureActive = false;
    private boolean mIsFreeMode = false;
    private boolean mInLongPress;

    private Handler mHandler = new Handler(){

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            switch (msg.what){

                case SINGLE_TAP:
                    if(mGestureListener != null) mGestureListener.onSingleTap();
                    break;
                case QUICK_SINGLE_TAP:
                    if(mGestureListener != null) mGestureListener.onQucikSingleTap();
                    break;
                case DOUBLE_TAP:
                    if(mGestureListener != null) mGestureListener.onDoubleTap();
                    break;
                case LONGPRESS:
                    mInLongPress = true;
                    if(mGestureListener != null) mGestureListener.onLongPress();
                    break;
                case SWIPE_UP:
                    if(mGestureListener != null) mGestureListener.onScrollUp();
                    break;
                case SWIPE_DOWN:
                    if(mGestureListener != null) mGestureListener.onScrollDown();
                    break;
                case SWIPE_LEFT:
                    if(mGestureListener != null) mGestureListener.onScrollLeft();
                    break;
                case SWIPE_RIGHT:
                    if(mGestureListener != null) mGestureListener.onScrollRight();
                    break;
                case MOVE:
                    if(mGestureListener != null) mGestureListener.onMove();
                    break;
                case DOWN:
                    if(mGestureListener != null) mGestureListener.onDown();
                    break;
                case MOVE_FINISH:
                    if(mBallEventListener != null) mBallEventListener.onBallMoveFinish();
                    break;
                case HOME_KEY_PRESSED:
                    if(mBallEventListener != null) mBallEventListener.onHomeKeyPressed();
                    break;
                case RECENT_KEY_PRESSED:
                    if(mBallEventListener != null) mBallEventListener.onRecentKeyPressed();
                    break;
                case SET_ALPHA:
                    getBackground().setAlpha(mAlpha);
                    break;
                case FEEDBACK:
                    mParentLayout.setPadding(FEED_ZOOM,FEED_ZOOM,FEED_ZOOM,FEED_ZOOM);
                    break;
                default:
                    break;
            }
        }
    };


    public void updatePosition() {

        if(getParent() != null){

            mWindowManager.updateViewLayout(mParentLayout,mWinLayoutParams);
        }
    }

    public void activateFreeMode() {

        mIsFreeMode = true;
    }

    public void cancelFreeMode(){

        mIsFreeMode = false;
    }


    public interface OnGestureListener {

        void onSingleTap();

        void onQucikSingleTap();

        void onDoubleTap();

        void onLongPress();

        void onScrollUp();

        void onScrollDown();

        void onScrollLeft();

        void onScrollRight();

        void onMove();

        void onDown();

    }

    public interface OnBallEventListener{

        void onBallMoveFinish();

        void onHomeKeyPressed();

        void onRecentKeyPressed();
    }


    public BallView(Context context) {

        super(context);

        mContext = context;

        mPreferences = FloatingBallUtils.getMultiProcessPreferences();

        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

        //系统能识别的最小滑动距离
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

        mTouchSlopSquare = mTouchSlop * mTouchSlop;

        mCanMove = mPreferences.getBoolean("moveSwitch", false);
        mSize = mPreferences.getInt("ballsize", (MIN_BALL_SIZE + MAX_BALL_SIZE) / 2);
        mAlpha = mPreferences.getInt("ballalpha", (MIN_BALL_ALPHA + MAX_BALL_ALPHA) / 2);
        mTheme = mPreferences.getString("theme", "默认");


        setTheme(mTheme);

        initParentLayout();

        initLayoutParams();
        initAnimation();

        setClickable(true);
    }

    public void setTheme(String theme) {

        mTheme = theme;

        switch (theme) {
            case "默认":
                setBackground(getResources().getDrawable(R.drawable.theme1));
                break;
            case "主题二":
                setBackground(getResources().getDrawable(R.drawable.theme2));
                break;
            case "主题三":
               setBackground(getResources().getDrawable(R.drawable.theme3));
                break;
            case "主题四":
                setBackground(getResources().getDrawable(R.drawable.theme4));
                break;
            case "UFO":
                setBackground(getResources().getDrawable(R.drawable.ufo));
                break;
            case "自定义":

                if(FloatingBallUtils.isFileExist("/RelaxFinger/DIY.png")) {

                    String filePath = Environment.getExternalStorageDirectory().getAbsolutePath()
                            + "/RelaxFinger/DIY.png";

                    setBackground(BitmapDrawable.createFromPath(filePath));

                }else{

                    setBackground(getResources().getDrawable(R.drawable.theme1));

                    mPreferences.put("theme", "默认");
                }

                break;
            default:
                setBackground(getResources().getDrawable(R.drawable.theme1));
                mPreferences.put("theme", "默认");
                break;
        }



        getBackground().setAlpha(mAlpha);


    }

    public void showNotification(Drawable notifyIcon) {

        Drawable roundIcon = ImageUtils.toRoundDrawable(notifyIcon,DensityUtil.dip2px(mContext,mSize));

        setBackground(roundIcon);

        showNotifyAnim();
    }

    public void clearNotification(){

        setTheme(mTheme);
    }

    public void setAutoMoveTheme(boolean isAutoMove){

        if(isAutoMove){

            setBackground(getResources().getDrawable(R.drawable.ufo));

            getBackground().setAlpha(mAlpha);

        }else {

            setTheme(mTheme);
        }
    }

    public void showNotifyAnim(){

        ObjectAnimator shakeAnim = FloatingBallUtils.shakeAnim(this,1.0f);

        shakeAnim.setupEndValues();

        shakeAnim.start();


    }

    private void initAnimation() {

        mZoomInAnim = new ScaleAnimation(0f, 1f, 0f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        mZoomInAnim.setDuration(100);

        mZoomOutAnim = new ScaleAnimation(1f, 0f, 1f, 0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        mZoomOutAnim.setDuration(100);


        mZoomOutAnim.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {

                mWindowManager.removeView(mParentLayout);
                mParentLayout.removeView(BallView.this);

            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
    }

    public void setOnGestureListener(OnGestureListener listener) {

        mGestureListener = listener;
    }

    public void setOnMoveFinishListener(OnBallEventListener listener){

        mBallEventListener = listener;
    }

    private void initParentLayout() {

        mParentLayout = new InnerLinearLayout(mContext);

        mParentLayout.setPadding(FEED_ZOOM,FEED_ZOOM,FEED_ZOOM,FEED_ZOOM);


    }

    private void initLayoutParams() {

        mWinLayoutParams = new WindowManager.LayoutParams();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

            mWinLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;

        }else {

            mWinLayoutParams.type = WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
        }

        mWinLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS |
        WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
        mWinLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;

        mWinLayoutParams.x = mPreferences.getInt("ballWmParamsX", FloatingBallUtils.getScreenWidth() - mSize);
        mWinLayoutParams.y = mPreferences.getInt("ballWmParamsY", FloatingBallUtils.getScreenHeight() / 2 - mSize / 2);

        mWinLayoutParams.width = mSize;
        mWinLayoutParams.height = mSize;

        mWinLayoutParams.format = PixelFormat.TRANSLUCENT;
    }

    public WindowManager.LayoutParams getWindowLayoutParams(){

        return mWinLayoutParams;
    }

    private long lastTime = 0;

    private void touchDownFeedback() {

        getBackground().setAlpha(200);

        mParentLayout.setPadding(0,0,0,0);


        lastTime = System.currentTimeMillis();

        if(mHandler.hasMessages(SET_ALPHA)){

            mHandler.removeMessages(SET_ALPHA);
        }
        mHandler.sendEmptyMessageDelayed(SET_ALPHA,3000);

    }

    private void touchUpFeedback() {

        if(System.currentTimeMillis()-lastTime < 50){

            mHandler.sendEmptyMessageDelayed(FEEDBACK,20);


        }else {

            mParentLayout.setPadding(FEED_ZOOM,FEED_ZOOM,FEED_ZOOM,FEED_ZOOM);
        }

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()){

            case MotionEvent.ACTION_DOWN:

                touchDownFeedback();
                //判断是否双击
                boolean hadTapMessage = mHandler.hasMessages(SINGLE_TAP);
                if (hadTapMessage) mHandler.removeMessages(SINGLE_TAP);
                if (hadTapMessage) {

                    mHandler.sendEmptyMessage(DOUBLE_TAP);
                    mIsDoubleTapping = true;
                    return true;

                } else {

                    mIsDoubleTapping = false;
                }

                mInLongPress = false;
                mHandler.sendEmptyMessageDelayed(LONGPRESS,LONG_PRESS_TIMEOUT);

                mDownX = (int) event.getRawX();
                mDownY = (int) event.getRawY();

                mHasMoved = false;
                mHasScrolled = false;
                mCanMove = mPreferences.getBoolean("moveSwitch",false);
                break;
            case MotionEvent.ACTION_MOVE:

                if(mIsDoubleTapping){

                   return true;
                }

                final int deltaX = (int) (event.getRawX() - mDownX);
                final int deltaY = (int) (event.getRawY() - mDownY);

                int distance = (deltaX * deltaX) + (deltaY * deltaY);

                //判断是否为滑动
                if(distance>mTouchSlopSquare){

                    mHasScrolled = true;
                    mHandler.removeMessages(LONGPRESS);

                    //移动悬浮球
                    if((mCanMove || mIsFreeMode) && mGestureListener != null){

                        mWinLayoutParams.x = (int)(event.getRawX()) - mSize/2;
                        mWinLayoutParams.y = (int)(event.getRawY()) - mSize/2;

                        mWindowManager.updateViewLayout(mParentLayout,mWinLayoutParams);

                        mHandler.sendEmptyMessage(MOVE);

                        mHasMoved = true;

                        return true;
                    }

                    //解析上下左右手势
                    if(!mGestureActive){

                        handleGesture(event);

                        return true;

                    }

                }

                break;
            case MotionEvent.ACTION_UP:

                touchUpFeedback();

                if(mIsDoubleTapping){

                    return true;
                }

                if(mHandler.hasMessages(LONGPRESS)){

                    mHandler.removeMessages(LONGPRESS);
                }

                if(!mInLongPress && !mHasScrolled){

                    if(!mIsDoubleTapping){

                        mHandler.sendEmptyMessageDelayed(SINGLE_TAP,DOUBLE_TAP_TIMEOUT);
                    }

                    mHandler.sendEmptyMessage(QUICK_SINGLE_TAP);
                }


                if(mHasMoved){

                    mHandler.sendEmptyMessage(MOVE_FINISH);
                    mHasMoved = false;
                }

                mGestureActive = false;

                break;
            default:
                touchUpFeedback();
                if(mHasMoved){

                    mHandler.sendEmptyMessage(MOVE_FINISH);
                    mHasMoved = false;
                }
                mGestureActive = false;
                break;
        }

        return super.onTouchEvent(event);
    }

    /**
     * 解析上下左右手势
     * @param event
     */
    private void handleGesture(MotionEvent event) {

        float yDistance = mDownY - event.getRawY();
        float xDistance = mDownX - event.getRawX();
        float yDistanceABS = Math.abs(yDistance);
        float xDistanceABS = Math.abs(xDistance);
        double x = Math.atan2(yDistanceABS, xDistanceABS);
        double angle = x * 180 / Math.PI;

        //当这个角度大于45度时候 我们就认为他是上下方向的滑动
        if (angle > 45) {

            if (yDistance < 0) {
                mHandler.sendEmptyMessage(SWIPE_DOWN);//手指往下滑动
                mGestureActive = true;
            } else {
                mHandler.sendEmptyMessage(SWIPE_UP);//手指往上滑动
                mGestureActive = true;
            }

        } else {
            //当这个角度小于45度时候 我们就认为他是左右方向的滑动
            if (xDistance < 0) {
                mHandler.sendEmptyMessage(SWIPE_RIGHT);//手指往右滑
                mGestureActive = true;
            } else {
                mHandler.sendEmptyMessage(SWIPE_LEFT);//手指往左边滑
                mGestureActive = true;
            }
        }
    }


    public void setMove(boolean canMove){

        mCanMove = canMove;
    }

    public void setAlpha(int alpha){

        mAlpha = alpha;

        getBackground().setAlpha(mAlpha);


    }

    public void setBallSize(int size){

        mSize = size;
        mWinLayoutParams.width = mSize;
        mWinLayoutParams.height = mSize;
    }

    public int getBallSize(){

        return mSize;
    }

    public void show(){

        if(getParent() == null){

            mParentLayout.addView(this);

            mWindowManager.addView(mParentLayout,mWinLayoutParams);

            startAnimation(mZoomInAnim);
        }

    }

    public void quickShow(){

        if(getParent() == null){

            mParentLayout.addView(this);

            mWindowManager.addView(mParentLayout,mWinLayoutParams);

        }
    }

    public void hide(){

        if(getParent() != null){

            startAnimation(mZoomOutAnim);
        }

    }

    public void quickHide(){

        if(getParent() != null){

            mWindowManager.removeView(mParentLayout);
            mParentLayout.removeView(BallView.this);
        }

    }

    public class InnerLinearLayout extends LinearLayout{


        public InnerLinearLayout(Context context) {
            super(context);
        }

        //获取home键和多任务键事件
        public void onCloseSystemDialogs(String reason) {

            if (reason != null && reason.equals("homekey")) {

                mHandler.sendEmptyMessage(HOME_KEY_PRESSED);

            } else if (reason != null && reason.equals("recentapps")) {

                mHandler.sendEmptyMessage(RECENT_KEY_PRESSED);
            }

        }

    }
}