package cn.sunjian.coolmenu;

import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.LayoutTransition;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.database.Observable;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.graphics.PointF;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.support.annotation.IntDef;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * 炫酷大风车
 * Created by sunjian on 2017/1/17.
 */

public class CoolMenu extends ViewGroup {

    // 惯性滑动,拖拽, 旋转事件,这几个变量有点尴尬,也不想删除了
    public static final int IDLE = 0;
    public static final int ROTATE = 1;
    public static final int FLING = 2;
    public static final int DAGGLE = 3;

    public static final int WHAT_HANDLE_FLING = 0;

//    private static final int WHAT_HANDLE_ADD_DRAG_VIEW = 1;

    private static final int ANIM_SHOW_DURATION = 1600;

    private static final int ANIM_DISMISS_DURATION = 2400;


    private final float DAGGLE_RANGE = dp2px(10);

    // 修改这个值可以改变滑行速度
    private static final int VELOCITYFLING = 5;
    static final float CLICK_ANGLE = 0.2F;

    int state = IDLE;

    @IntDef({IDLE, ROTATE, FLING, DAGGLE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Action {

    }

    //角度
    float mAngle = 0;

    //边长
    int mEdge;

    //屏幕距离
    private int screenDistance;

    // 记录上一次的x,y坐标
    private float mLastX;
    private float mLastY;

    // 记录第一次的角度
    private float mFirstAngle;

    private float mPerAngle;

    //开始时间
    private long mStartTime;

    //拖拽的view
    private ImageView mDragView;
    //拖拽的原view
    private View mStartDragView;
    //拖拽的图片
    private Bitmap mDragBitmap;

    private WindowManager.LayoutParams mWindowLayoutParams;

    private WindowManager mWindowManager;
    //震动
    Vibrator mVibrator;

    private int mStatusBarHeight = -1;

    private boolean mIsEnterDaggle = false;

    //前一个位置
    private int mPreDragMovePosition = -1;

    //缓存位置的x,y
    private List<CoolMenuBean> mCoolMenuBeanList = new ArrayList<>();

    //当前位置
    private int mCurrentDragMovePosition = -1;

    //拖拽移动时记住移动的position
    private int[] mMovePosArr;

    //线程统一管理
    ScheduledExecutorService mExecutor = Executors.newSingleThreadScheduledExecutor();
    private ScheduledFuture<?> mFuture;

    Handler mHandle = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case WHAT_HANDLE_FLING:
                    layoutChild();
                    break;
//                case WHAT_HANDLE_ADD_DRAG_VIEW:
//                    mWindowManager.addView(mDragView, mWindowLayoutParams);
//                    break;
            }
        }
    };

    private Adapter mAdapter;

    private final CoolMenuDataObserver mObserver = new CoolMenuDataObserver();

    private int mCurrentChildCount = -1;

    OnItemClickListener mItemClickListener;

    OnItemDragListener mItemDragListener;

    OnItemFlingListener mItemFlingListener;

    private boolean mIsDrag = true;

    private boolean mIsFling = true;

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

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

    public CoolMenu(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        initData(context);

        if (attrs != null) {

            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.coolmenu, 0, 0);

            @LayoutRes int centerResId = a.getResourceId(R.styleable.coolmenu_centerLayout, R.layout.center);

            mIsDrag = a.getBoolean(R.styleable.coolmenu_isDrag, mIsDrag);

            mIsFling = a.getBoolean(R.styleable.coolmenu_isFling, mIsFling);

            View.inflate(context, centerResId, this);
        }

        setLayoutTransition(new LayoutTransition());

    }

    /**
     * 关于孩子的个数没有限制,但是多了肯定会卡,而且不美观
     *
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int childCount = getChildCount();

        if (childCount <= 0) {
            throw new RuntimeException("child count must be more than 1");
        }

        int width = MeasureSpec.getSize(widthMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);

        int height = MeasureSpec.getSize(heightMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        int edge;

        //存储孩子宽高数组
        int[] childsWidth = new int[childCount];
        int[] childsHeight = new int[childCount];

        if (widthMode == MeasureSpec.EXACTLY && heightMode == MeasureSpec.EXACTLY) {

            edge = width >= height ? height : width;

        } else {

            for (int i = 0; i < childCount; i++) {

                View child = getChildAt(i);

                if (child.getVisibility() == View.GONE) {
                    continue;
                }

                measureChild(child, widthMeasureSpec, heightMeasureSpec);
                MarginLayoutParams lp = (MarginLayoutParams) child
                        .getLayoutParams();

                int childWidth = child.getMeasuredWidth() + lp.leftMargin
                        + lp.rightMargin;
                int childHeight = child.getMeasuredHeight() + lp.topMargin
                        + lp.bottomMargin;

                childsWidth[i] = childWidth;
                childsHeight[i] = childHeight;

            }

            Arrays.sort(childsWidth);
            Arrays.sort(childsHeight);

            if (childCount == 1) {
                edge = childsWidth[0] > childsHeight[0] ? childsWidth[0] : childsHeight[0];
                edge = edge > screenDistance ? screenDistance : edge;
            } else if (childCount == 2) {
                int childW = childsWidth[0] + childsWidth[1];
                int childH = childsHeight[0] + childsHeight[1];
                edge = childW > childH ? childW : childH;
                edge = edge > screenDistance ? screenDistance : edge;
            } else {
                int childW = childsWidth[childCount - 1] + childsWidth[childCount - 2] + childsWidth[childCount - 3];
                int childH = childsHeight[childCount - 1] + childsHeight[childCount - 2] + childsHeight[childCount - 3];
                edge = childW > childH ? childW : childH;
                edge = edge > screenDistance ? screenDistance : edge;
            }
        }

        this.mEdge = edge;

        int measured = MeasureSpec.makeMeasureSpec(edge, MeasureSpec.EXACTLY);

        setMeasuredDimension(measured, measured);

        for (int i = 0; i < childCount; i++) {

            View child = getChildAt(i);
            int m = MeasureSpec.makeMeasureSpec((int) (edge * (i == 0 ? 0.8f : 0.6f) * 1.0f / 3), MeasureSpec.EXACTLY);
            child.measure(m, m);
        }

    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {

        layoutChild();
    }

    float mDragAngle;

    //没有用GestureDetector,纯手工,更方便你的学习
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {

        float x = event.getX();
        float y = event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:

                mStartTime = System.currentTimeMillis();

                cancelFuture();

                mPerAngle = 0;

                mLastX = x;
                mLastY = y;

                mFirstAngle = getAngle(x, y);

                break;
            case MotionEvent.ACTION_MOVE:

                float start = getAngle(mLastX, mLastY);

                float end = getAngle(x, y);

                mAngle = (mAngle + end - start) % 360;

                mPerAngle = end - start;

                mLastX = x;
                mLastY = y;

                if (!mIsEnterDaggle) {

                    long differMoveTime = System.currentTimeMillis() - mStartTime;

                    if (differMoveTime > ViewConfiguration.getLongPressTimeout()) {

                        if (Math.abs(end - mFirstAngle) < CLICK_ANGLE) {
                            //处理拖拽事件
                            float rawX = event.getRawX() - mEdge * 0.1F;
                            float rawY = event.getRawY() - mEdge * 0.1F - mStatusBarHeight;
                            //判断是否能拖拽
                            if (isCanDrag(rawX, rawY) && mIsDrag) {
                                mDragAngle = mAngle;
                                startDragEvent(rawX, rawY);
                            }
                        } else {

                            state = ROTATE;
                        }
                        mIsEnterDaggle = true;
                    } else {
                        state = ROTATE;
                    }
                }

                if (state == ROTATE) {
                    // 重新布局
                    layoutChild();
                }

                break;
            case MotionEvent.ACTION_UP:

                mIsEnterDaggle = false;

                long differUpTime = System.currentTimeMillis() - mStartTime;

                if (Math.abs(mPerAngle) < CLICK_ANGLE && differUpTime < ViewConfiguration.getTapTimeout()) {
                    //处理点击事件

                    int childCount = getChildCount();

                    for (int i = 0; i < childCount; i++) {

                        if (i != 0) {

                            View child = getChildAt(i);
                            int[] location = new int[2];
                            child.getLocationOnScreen(location);

                            float rawX = event.getRawX() - mEdge * 0.1F;
                            float rawY = event.getRawY() - mEdge * 0.1F - mStatusBarHeight;

                            if (isPointInView(rawX, rawY, location[0], location[1])) {

                                if (mItemClickListener != null) {
                                    mItemClickListener.onItemClick(child, i - 1);
                                }

                                state = IDLE;
                                break;
                            }
                        }
                    }

                } else if (Math.abs(mPerAngle) >= CLICK_ANGLE && differUpTime < ViewConfiguration.getTapTimeout() && mIsFling) {
                    //处理惯性滑动事件
                    // 计算,每秒移动的角度
                    float anglePerSecond = mPerAngle * 1000
                            / differUpTime;

                    startScroll(anglePerSecond);

                }

                break;
        }
        return super.dispatchTouchEvent(event);
    }

    @Override
    protected void onFinishInflate() {

        super.onFinishInflate();

        int childCount = getChildCount();
        if (childCount > 1) {

            mMovePosArr = new int[childCount - 1];
        }
    }

    //不多BB,通通拦截
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        if (state == DAGGLE && mDragView != null) {
            //处理拖拽
            switch (event.getAction()) {
                case MotionEvent.ACTION_MOVE:

                    float moveX = event.getRawX();
                    float moveY = event.getRawY();
                    //拖动item
                    onDragView(moveX - mEdge * 0.1F, moveY - mEdge * 0.1F - mStatusBarHeight);
                    break;
                case MotionEvent.ACTION_UP:

                    float upX = event.getRawX();
                    float upY = event.getRawY();
                    onStopDrag(upX, upY);
                    break;
            }
        }
        return true;
    }

    @Override
    protected LayoutParams generateDefaultLayoutParams() {

        int wrap_content = getResources().getDimensionPixelOffset(R.dimen.cool_menu_wrap_content);
        return new MarginLayoutParams(wrap_content, wrap_content);
    }

    @Override
    protected LayoutParams generateLayoutParams(LayoutParams p) {
        return new MarginLayoutParams(p);
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }

    //初始化数据
    private void initData(Context context) {

        DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            //根据资源ID获取响应的尺寸值
            mStatusBarHeight = getResources().getDimensionPixelSize(resourceId);
        }
        screenDistance = displayMetrics.widthPixels > displayMetrics.heightPixels ? displayMetrics.heightPixels : displayMetrics.widthPixels;
        mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        mWindowLayoutParams = new WindowManager.LayoutParams();
        mWindowLayoutParams.format = PixelFormat.TRANSLUCENT; //图片之外的其他地方透明
        mWindowLayoutParams.gravity = Gravity.TOP | Gravity.LEFT;
        mWindowLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        mWindowLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        mWindowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
    }

    public void setDrag(boolean isDrag) {
        this.mIsDrag = isDrag;
    }

    public void setFling(boolean isFling) {
        this.mIsFling = isFling;
    }

    //能否拖拽
    private boolean isCanDrag(float rawX, float rawY) {

        boolean isCanDrag = false;
        int childCount = getChildCount();
        mCoolMenuBeanList.clear();

        for (int i = 0; i < childCount; i++) {

            if (i != 0) {

                View child = getChildAt(i);
                int[] location = new int[2];
                child.getLocationOnScreen(location);

                if (!isCanDrag) {

                    if (isPointInView(rawX, rawY, location[0], location[1])) {

                        isCanDrag = true;
                        mStartDragView = child;
                        mCurrentDragMovePosition = i - 1;
                        mPreDragMovePosition = mCurrentDragMovePosition;
                        mStartDragView.setDrawingCacheEnabled(true);
                        mDragBitmap = Bitmap.createBitmap(mStartDragView.getDrawingCache());
                        mStartDragView.destroyDrawingCache();
                    }
                }

                mMovePosArr[i - 1] = i - 1;
                mCoolMenuBeanList.add(new CoolMenuBean(location[0], location[1] - mStatusBarHeight, i - 1));
            }
        }

        return isCanDrag;
    }

    //判断触摸点是否在view中
    private boolean isPointInView(float rawX, float rawY, int x, int y) {

        return rawX >= x - DAGGLE_RANGE * 3 && rawX <= (x + DAGGLE_RANGE + mEdge * 0.1F)
                && rawY >= y - mStatusBarHeight - DAGGLE_RANGE * 3
                && rawY <= (y + DAGGLE_RANGE - mStatusBarHeight + mEdge * 0.1F);
    }

    //根据x,y拖拽view
    private void onDragView(float moveX, float moveY) {

        mWindowLayoutParams.x = (int) moveX;
        mWindowLayoutParams.y = (int) moveY;
        mWindowManager.updateViewLayout(mDragView, mWindowLayoutParams); //更新镜像的位置

        if (mItemDragListener != null) {

            mItemDragListener.onDragMove(mStartDragView, moveX, moveY, mCurrentDragMovePosition);
        }

        onSwapItem(moveX, moveY);
    }

    //根据x,y交换view
    private void onSwapItem(float moveX, float moveY) {

        if (!mCoolMenuBeanList.isEmpty()) {

            for (CoolMenuBean coolMenuBean : mCoolMenuBeanList) {

                int originalPos = coolMenuBean.getPosition();

                if (isPointInView(moveX, moveY, coolMenuBean.getX(), coolMenuBean.getY()) && mMovePosArr[originalPos] != mCurrentDragMovePosition) {

                    View child = getChildAt(mCurrentDragMovePosition + 1);
                    View moveChild = getChildAt(mMovePosArr[originalPos] + 1);
                    mMovePosArr[mPreDragMovePosition] = mMovePosArr[originalPos];
                    mPreDragMovePosition = originalPos;
                    mMovePosArr[originalPos] = mCurrentDragMovePosition;
                    int moveLeft = moveChild.getLeft();
                    int moveTop = moveChild.getTop();
                    int moveRight = moveChild.getRight();
                    int moveBottom = moveChild.getBottom();
                    moveChild.layout(child.getLeft(), child.getTop(), child.getRight(), child.getBottom());
                    child.layout(moveLeft, moveTop, moveRight, moveBottom);
                    break;
                }
            }
        }
    }

    //停止拖拽
    private void onStopDrag(float upX, float upY) {

        int[] inflate = dragFinishInflate((int) upX, (int) upY);

//        CoolMenuBean bean = mCoolMenuBeanList.get(mMovePosArr[mCurrentDragMovePosition]);//用这个有时候不准

        new DragValueAnimator(mDragView, new PointF(upX - mEdge * 0.1F, upY - mEdge * 0.1F - mStatusBarHeight), new PointF(inflate[0], inflate[1]))
                .addDragListener(new DragValueAnimator.DragAnimatorListener() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        mStartDragView.setVisibility(VISIBLE);
                        removeDragView();
                        state = IDLE;
                        setLayoutTransition(new LayoutTransition());
                        if (mItemDragListener != null) {
                            mItemDragListener.onDragEnd(mStartDragView, mCurrentDragMovePosition);
                        }
                    }
                })
                .addDragUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        PointF animatedValue = (PointF) animation.getAnimatedValue();
                        mWindowLayoutParams.x = (int) animatedValue.x;
                        mWindowLayoutParams.y = (int) animatedValue.y;
                        mWindowManager.updateViewLayout(mDragView, mWindowLayoutParams);
                    }
                })
                .start();
    }

    //拖拽结束,恢复布局
    private int[] dragFinishInflate(int upX, int upY) {

        int[] dragPosition = new int[]{upX, upY};
        //返回拖拽时的角度
        mAngle = mDragAngle;

        int childCount = getChildCount();
        if (childCount > 1) {

            List<View> list = new ArrayList<View>();

            for (int i = 1; i < childCount; i++) {

                View child = getChildAt(mMovePosArr[i - 1] + 1);

                if (child.getVisibility() == INVISIBLE) {

                    mStartDragView = child;
                    child.getLocationOnScreen(dragPosition);
                    dragPosition[1] = dragPosition[1] - mStatusBarHeight;

                }
                list.add(child);
            }

            removeViewsInLayout(1, childCount - 1);

            for (int i = 0; i < list.size(); i++) {

                View child = list.get(i);
                addViewInLayout(child, i + 1, child.getLayoutParams());
            }

            requestLayout();
        }

        return dragPosition;
    }

    //是否是逆时针
    private boolean isAntiClockWise(float downY, float anglePerSecond) {

        float centerY = getMeasuredHeight() * 0.5f;
        if (downY >= 0 && downY <= centerY) {
            return anglePerSecond < 0;
        }
        return anglePerSecond > 0;
    }

    // 根据触摸的位置,计算角度
    private float getAngle(float currentX, float currentY) {

        double x = currentX - mEdge * 0.5f;
        double y = mEdge * 0.5f - currentY;
        return (float) Math.toDegrees(Math.atan2(y, x));
    }

    public void cancelFuture() {

        if (mFuture != null && !mFuture.isCancelled()) {
            mFuture.cancel(true);
            mFuture = null;
        }
    }

    private void startDragEvent(float downX, float downY) {

        cancelFuture();
        state = DAGGLE;

        setLayoutTransition(null);

        if (mItemDragListener != null) {
            mItemDragListener.onDragStart(mStartDragView, mCurrentDragMovePosition);
        }
        mStartDragView.setVisibility(View.INVISIBLE);//隐藏该item
        mVibrator.vibrate(50); //震动一下
        //根据我们按下的点显示item镜像
        createDragView((int) downX, (int) downY);
//        mFuture = mExecutor.schedule(new CoolMenuDragRunnable(this, downX, downY), 0, TimeUnit.MILLISECONDS);
    }

    protected final void startScroll(float velocity) {

        cancelFuture();
        state = FLING;
        if (mItemFlingListener != null) {
            mItemFlingListener.onFlingStart();
        }
        mFuture = mExecutor.scheduleWithFixedDelay(new CoolMenuVelocityTimerTask(this, velocity), 0, VELOCITYFLING, TimeUnit.MILLISECONDS);
    }

    //创建拖动的镜像
    protected final void createDragView(int downX, int downY) {

        mWindowLayoutParams.x = downX;
        mWindowLayoutParams.y = downY;
        mDragView = new ImageView(getContext());
        mDragView.setImageBitmap(mDragBitmap);
        mWindowManager.addView(mDragView, mWindowLayoutParams);
//        mHandle.sendEmptyMessage(WHAT_HANDLE_ADD_DRAG_VIEW);
    }

    //从界面上面移动拖动镜像
    private void removeDragView() {

        if (mDragView != null) {
            mWindowManager.removeView(mDragView);
            mDragView = null;
        }
    }

    //摆放
    private void layoutChild() {

        int childCount = getChildCount();
        int childPerAngle = 0;
        if (childCount > 1) {
            childPerAngle = (int) (360 * 1.0f / (childCount - 1));
        }

        for (int i = 0; i < childCount; i++) {

            View child = getChildAt(i);

            if (child.getVisibility() == GONE) {
                continue;
            }

            int width = child.getMeasuredWidth();
            int height = child.getMeasuredHeight();
            int left;
            int top;
            int right;
            int bottom;

            if (i == 0) {

                left = (int) (mEdge * 0.5f - width * 0.5f);
                top = (int) (mEdge * 0.5f - height * 0.5f);
                right = (int) (mEdge * 0.5f + width * 0.5f);
                bottom = (int) (mEdge * 0.5f + height * 0.5f);
            } else {

                left = (int) (1.0f * mEdge / 3 * Math.cos(Math.toRadians(mAngle + (i - 1) * childPerAngle)) - width * 0.5f + 0.5f * mEdge);
                top = (int) (0.5f * mEdge - 1.0f * mEdge / 3 * Math.sin(Math.toRadians(mAngle + (i - 1) * childPerAngle)) - height * 0.5f);
                right = (int) (1.0f * mEdge / 3 * Math.cos(Math.toRadians(mAngle + (i - 1) * childPerAngle)) + width * 0.5f + 0.5f * mEdge);
                bottom = (int) (0.5f * mEdge - 1.0f * mEdge / 3 * Math.sin(Math.toRadians(mAngle + (i - 1) * childPerAngle)) + height * 0.5f);
            }

            child.layout(left, top, right, bottom);
        }
    }

    private float dp2px(float dpValue) {
        final float scale = getResources().getDisplayMetrics().density;
        return dpValue * scale + 0.5f;
    }

    /**
     * 关于适配器的写法是模仿recyclerview,具体的可以看源码,有想法的同学可以联系我,因为关于圆盘我确实想不到太多,重点是个架构的学习
     *
     * @param adapter
     */
    public void setAdapter(@NonNull Adapter adapter) {

        int childCount = getChildCount();

        if (childCount > 1 && mAdapter == null) {
            throw new RuntimeException("static and dynamic can only have one");
        }

        int count = adapter.getItemCount();

        if (count == 0) return;

        this.mCurrentChildCount = count;

        mMovePosArr = new int[count];

        if (this.mAdapter != null) {
            this.mAdapter.unregisterAdapterDataObserver(mObserver);
        }

        this.mAdapter = adapter;

        this.mAdapter.registerAdapterDataObserver(mObserver);

        updateAdapterData(adapter, count);
    }

    public Adapter getAdapter() {

        return mAdapter;
    }

    //关于这里的优化,等有时间我会想想,暂时先暴力点
    private void updateAdapterData(@NonNull Adapter adapter, int count) {

        if (getChildCount() > 1) {
            removeViewsInLayout(1, mCurrentChildCount);
        }

        if (count != mCurrentChildCount) {

            this.mCurrentChildCount = count;
            mMovePosArr = new int[count];

        }

        //因为我们控件没有复用一说,所以直接搞
        for (int i = 0; i < count; i++) {

            int viewType = adapter.getItemViewType(i);

            ViewHolder holder = adapter.onCreateViewHolder(this, viewType);

            adapter.onBindViewHolder(holder, i);

            addViewInLayout(holder.itemView, i + 1, holder.itemView.getLayoutParams(), true);

        }

        requestLayout();

    }

    //设置监听
    public void setOnItemClickListener(OnItemClickListener listener) {
        this.mItemClickListener = listener;
    }

    public void setOnItemDragListener(OnItemDragListener listener) {
        this.mItemDragListener = listener;
    }

    public void setOnItemFlingListener(OnItemFlingListener listener) {
        this.mItemFlingListener = listener;
    }

    //显示动画,可以自己调
    public void show() {

        int childCount = getChildCount();
        if (childCount > 1) {

            mAngle = 0;//复位

            float x = 0.5f * mEdge;
            float y = 0.5f * mEdge;
            Animator[] anim = new Animator[childCount];

            for (int i = 0; i < childCount; i++) {

                View child = getChildAt(i);
                float pivotX = x - child.getLeft();
                float pivotY = y - child.getTop();
                child.setPivotX(pivotX);
                child.setPivotY(pivotY);
                float childX = 0.5f * child.getLeft() + child.getRight() * 0.5f;
                float childY = 0.5f * child.getTop() + 0.5f * child.getBottom();

                PropertyValuesHolder ca = PropertyValuesHolder.ofFloat("alpha", 0.5f, 1.0f);
                PropertyValuesHolder csx = PropertyValuesHolder.ofFloat("scaleX", 0, 1.0f);
                PropertyValuesHolder csy = PropertyValuesHolder.ofFloat("scaleY", 0, 1.0f);

                if (i == 0) {

                    anim[i] = ObjectAnimator.ofPropertyValuesHolder(child, ca, csx, csy);
                } else {
                    PropertyValuesHolder ctx = PropertyValuesHolder.ofFloat("translationX", -x + childX, 0);
                    PropertyValuesHolder cty = PropertyValuesHolder.ofFloat("translationY", -y + childY, 0);
                    PropertyValuesHolder cr = PropertyValuesHolder.ofFloat("rotation", 0, 360f);
                    anim[i] = ObjectAnimator.ofPropertyValuesHolder(child, ctx, cty, ca, csx, csy, cr);
                }
            }

            AnimatorSet set = new AnimatorSet();
            set.setDuration(ANIM_SHOW_DURATION);
            set.setInterpolator(new LinearInterpolator());
            set.playTogether(anim);
            set.start();
        }
    }

    //关闭时动画
    public void dismiss() {

        int childCount = getChildCount();
        if (childCount > 1) {

            float x = 0.5f * mEdge;
            float y = 0.5f * mEdge;

            Animator[] before = new Animator[childCount];

            Animator[] after = new Animator[childCount - 1];

            for (int i = 0; i < childCount; i++) {

                View child = getChildAt(i);
                float pivotX = x - child.getLeft();
                float pivotY = y - child.getTop();
                float childX = 0.5f * child.getLeft() + child.getRight() * 0.5f;
                float childY = 0.5f * child.getTop() + 0.5f * child.getBottom();

                child.setPivotX(pivotX);
                child.setPivotY(pivotY);

                PropertyValuesHolder ca = PropertyValuesHolder.ofFloat("alpha", 1.0f, 0);
                PropertyValuesHolder csx = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 0);
                PropertyValuesHolder csy = PropertyValuesHolder.ofFloat("scaleY", 1.0f, 0);

                if (i == 0) {

                    before[i] = ObjectAnimator.ofPropertyValuesHolder(child, ca, csx, csy);

                } else {

                    PropertyValuesHolder ctx = PropertyValuesHolder.ofFloat("translationX", 0, x - childX);
                    PropertyValuesHolder cty = PropertyValuesHolder.ofFloat("translationY", 0, y - childY);
                    PropertyValuesHolder cr = PropertyValuesHolder.ofFloat("rotation", 0, 360f);
                    before[i] = ObjectAnimator.ofPropertyValuesHolder(child, cr, ctx, cty);

                    PropertyValuesHolder cx = PropertyValuesHolder.ofFloat("translationX", x - childX, (childX - x) * 10);
                    PropertyValuesHolder cy = PropertyValuesHolder.ofFloat("translationY", y - childY, (childY - y) * 10);

                    after[i - 1] = ObjectAnimator.ofPropertyValuesHolder(child, cx, cy);
                }
            }

            AnimatorSet set = new AnimatorSet();
            AnimatorSet first = new AnimatorSet();
            AnimatorSet last = new AnimatorSet();
            first.playTogether(before);
            last.playTogether(after);
            set.setDuration(ANIM_DISMISS_DURATION);
            set.setInterpolator(new DecelerateInterpolator());
            set.play(first).before(last);
            set.start();

        }
    }


    @Override
    public void setLayoutTransition(LayoutTransition transition) {
        super.setLayoutTransition(transition);
    }

    private class CoolMenuDataObserver extends AdapterDataObserver {

        CoolMenuDataObserver() {
        }

        @Override
        public void onChanged() {

            if (mAdapter == null) return;

            int itemCount = mAdapter.getItemCount();
            if (itemCount == 0) {
                if (getChildCount() > 1) {

                    removeViews(1, mCurrentChildCount);
                }
            } else {

                updateAdapterData(mAdapter, itemCount);
            }
        }

        @Override
        public void onItemInserted(int position) {

            if (mAdapter == null) return;

            int itemCount = mAdapter.getItemCount();

            if (position > mCurrentChildCount) return;

            mCurrentChildCount = mCurrentChildCount > itemCount ? mCurrentChildCount - 1 : mCurrentChildCount + 1;

            mMovePosArr = new int[mCurrentChildCount];

            int viewType = mAdapter.getItemViewType(position);

            ViewHolder holder = mAdapter.onCreateViewHolder(CoolMenu.this, viewType);

            mAdapter.onBindViewHolder(holder, position);

            addViewInLayout(holder.itemView, position + 1, holder.itemView.getLayoutParams(), true);

            requestLayout();

        }

        @Override
        public void onItemRemoved(int position) {
            if (mAdapter == null) return;

            int itemCount = mAdapter.getItemCount();

            if (position + 1 > mCurrentChildCount) return;

            mCurrentChildCount = mCurrentChildCount > itemCount ? mCurrentChildCount - 1 : mCurrentChildCount + 1;

            mMovePosArr = new int[mCurrentChildCount];

            removeViewsInLayout(position + 1, 1);

            requestLayout();
        }
    }

    /**
     * 其实我想说holder毫无用处,因为现在的设计没有回收复用一说,如果以后需要,可增加相应api
     * 现在纯粹是为了分开findviewbyid,不影响具体UI逻辑
     */
    public static abstract class Adapter<VH extends ViewHolder> {

        private final AdapterDataObservable mObservable = new AdapterDataObservable();

        public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);

        public abstract void onBindViewHolder(VH holder, int position);

        //TraceCompat

        public int getItemViewType(int position) {
            return 0;
        }

        public abstract int getItemCount();

        public final void notifyDataSetChanged() {

            mObservable.notifyChanged();
        }

        public final boolean hasObservers() {

            return mObservable.hasObservers();
        }

        public void registerAdapterDataObserver(AdapterDataObserver observer) {

            mObservable.registerObserver(observer);
        }

        public void unregisterAdapterDataObserver(AdapterDataObserver observer) {

            mObservable.unregisterObserver(observer);
        }

        public final void notifyItemInserted(int position) {
            mObservable.notifyItemInserted(position);
        }

        public final void notifyItemRemoved(int position) {
            mObservable.notifyItemRemoved(position);
        }

    }

    static class AdapterDataObservable extends Observable<AdapterDataObserver> {

        public boolean hasObservers() {

            return !mObservers.isEmpty();
        }

        public void notifyChanged() {

            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onChanged();
            }
        }

        public void notifyItemInserted(int position) {
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onItemInserted(position);
            }
        }

        public void notifyItemRemoved(int position) {
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onItemRemoved(position);
            }
        }

    }

    public static abstract class AdapterDataObserver {

        public void onChanged() {
        }

        public void onItemInserted(int position) {
        }

        public void onItemRemoved(int position) {
        }

    }


    public static abstract class ViewHolder {
        public final View itemView;

        public ViewHolder(View itemView) {
            if (itemView == null) {
                throw new IllegalArgumentException("itemView may not be null");
            }
            this.itemView = itemView;
        }
    }

    //关于监听暂时定下这几个
    public interface OnItemClickListener {

        void onItemClick(View view, int position);
    }

    public interface OnItemDragListener {

        void onDragStart(View view, int position);

        void onDragMove(View view, float rawX, float rawY, int position);

        void onDragEnd(View view, int position);
    }

    public interface OnItemFlingListener {

        void onFlingStart();

        void onFlingEnd();
    }

}