package com.yc.videoview;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.os.Build;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.DecelerateInterpolator;


public class IFloatWindowImpl extends IFloatWindow {


    private FloatWindow.Builder mB;
    private FloatView mFloatView;
    private FloatLifecycle mFloatLifecycle;
    private boolean isShow;
    private boolean once = true;
    private ValueAnimator mAnimator;
    private TimeInterpolator mDecelerateInterpolator;

    private IFloatWindowImpl() {

    }

    IFloatWindowImpl(FloatWindow.Builder b) {
        mB = b;
        //这一步相当于创建系统级的window，通过windowManager添加view并且展示
        if (mB.mMoveType == MoveType.fixed) {
            if (Build.VERSION.SDK_INT >=Build.VERSION_CODES.N_MR1) {
                mFloatView = new FloatPhone(b.mApplicationContext);
            } else {
                mFloatView = new FloatToast(b.mApplicationContext);
            }
        } else {
            mFloatView = new FloatPhone(b.mApplicationContext);
            initTouchEvent();
        }
        mFloatView.setSize(mB.mWidth, mB.mHeight);
        mFloatView.setGravity(mB.gravity, mB.xOffset, mB.yOffset);
        mFloatView.setView(mB.mView);
        mFloatLifecycle = new FloatLifecycle(mB.mApplicationContext, mB.mShow, mB.mActivities, new LifecycleListener() {
            @Override
            public void onShow() {
                show();
            }

            @Override
            public void onHide() {
                hide();
            }

            @Override
            public void onPostHide() {
                postHide();
            }
        });
    }

    @Override
    public void show() {
        if (once) {
            mFloatView.init();
            once = false;
            isShow = true;
        } else {
            if (isShow) {
                return;
            }
            getView().setVisibility(View.VISIBLE);
            isShow = true;
        }
    }

    @Override
    public void hide() {
        if (once || !isShow) return;
        getView().setVisibility(View.INVISIBLE);
        isShow = false;
    }

    @Override
    void dismiss() {
        mFloatView.dismiss();
        isShow = false;
    }

    @Override
    public void updateX(int x) {
        checkMoveType();
        mB.xOffset = x;
        mFloatView.updateX(x);
    }

    @Override
    public void updateY(int y) {
        checkMoveType();
        mB.yOffset = y;
        mFloatView.updateY(y);
    }

    @Override
    public void updateX(int screenType, float ratio) {
        checkMoveType();
        mB.xOffset = (int) ((screenType == WindowScreen.WIDTH ?
                WindowUtil.getScreenWidth(mB.mApplicationContext) :
                WindowUtil.getScreenHeight(mB.mApplicationContext)) * ratio);
        mFloatView.updateX(mB.xOffset);

    }

    @Override
    public void updateY(int screenType, float ratio) {
        checkMoveType();
        mB.yOffset = (int) ((screenType == WindowScreen.WIDTH ?
                WindowUtil.getScreenWidth(mB.mApplicationContext) :
                WindowUtil.getScreenHeight(mB.mApplicationContext)) * ratio);
        mFloatView.updateY(mB.yOffset);

    }

    @Override
    public int getX() {
        return mFloatView.getX();
    }

    @Override
    public int getY() {
        return mFloatView.getY();
    }


    @Override
    public View getView() {
        return mB.mView;
    }

    void postHide() {
        if (once || !isShow) {
            return;
        }
        getView().post(new Runnable() {
            @Override
            public void run() {
                getView().setVisibility(View.INVISIBLE);
            }
        });
        isShow = false;
    }

    private void checkMoveType() {
        if (mB.mMoveType == MoveType.fixed) {
            throw new IllegalArgumentException("FloatWindow of this tag is not allowed to move!");
        }
    }

    private void initTouchEvent() {
        switch (mB.mMoveType) {
            case MoveType.free:
                break;
            default:
                getView().setOnTouchListener(onTouchListener);
                break;
        }
    }

    private View.OnTouchListener onTouchListener = new View.OnTouchListener() {
        float lastX, lastY, changeX, changeY;
        int newX, newY;
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    lastX = event.getRawX();
                    lastY = event.getRawY();
                    cancelAnimator();
                    break;
                case MotionEvent.ACTION_MOVE:
                    changeX = event.getRawX() - lastX;
                    changeY = event.getRawY() - lastY;
                    newX = (int) (mFloatView.getX() + changeX);
                    newY = (int) (mFloatView.getY() + changeY);
                    mFloatView.updateXY(newX, newY);
                    lastX = event.getRawX();
                    lastY = event.getRawY();
                    break;
                case MotionEvent.ACTION_UP:
                    switch (mB.mMoveType) {
                        case MoveType.slide:
                            int startX = mFloatView.getX();
                            int endX = (startX * 2 + v.getWidth() >
                                    WindowUtil.getScreenWidth(mB.mApplicationContext)) ?
                                    WindowUtil.getScreenWidth(mB.mApplicationContext) - v.getWidth() : 0;
                            mAnimator = ObjectAnimator.ofInt(startX, endX);
                            mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                                @Override
                                public void onAnimationUpdate(ValueAnimator animation) {
                                    int x = (int) animation.getAnimatedValue();
                                    mFloatView.updateX(x);
                                }
                            });
                            startAnimator();
                            break;
                        case MoveType.back:
                            PropertyValuesHolder pvhX = PropertyValuesHolder.ofInt("x", mFloatView.getX(), mB.xOffset);
                            PropertyValuesHolder pvhY = PropertyValuesHolder.ofInt("y", mFloatView.getY(), mB.yOffset);
                            mAnimator = ObjectAnimator.ofPropertyValuesHolder(pvhX, pvhY);
                            mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                                @Override
                                public void onAnimationUpdate(ValueAnimator animation) {
                                    int x = (int) animation.getAnimatedValue("x");
                                    int y = (int) animation.getAnimatedValue("y");
                                    mFloatView.updateXY(x, y);
                                }
                            });
                            startAnimator();
                            break;
                        default:
                            break;
                    }
                    break;
                default:
                    break;

            }
            return false;
        }
    };

    /**
     * 开启动画
     */
    private void startAnimator() {
        if (mB.mInterpolator == null) {
            if (mDecelerateInterpolator == null) {
                mDecelerateInterpolator = new DecelerateInterpolator();
            }
            mB.mInterpolator = mDecelerateInterpolator;
        }
        mAnimator.setInterpolator(mB.mInterpolator);
        mAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mAnimator.removeAllUpdateListeners();
                mAnimator.removeAllListeners();
                mAnimator = null;
            }
        });
        mAnimator.setDuration(mB.mDuration).start();
    }

    /**
     * 关闭动画
     */
    private void cancelAnimator() {
        if (mAnimator != null && mAnimator.isRunning()) {
            mAnimator.cancel();
        }
    }

}
