package com.kongzue.dialogx.dialogs;

import static android.view.View.OVER_SCROLL_NEVER;
import static android.view.View.VISIBLE;

import android.animation.ValueAnimator;
import android.app.Activity;
import android.graphics.Outline;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.view.ViewTreeObserver;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.DecelerateInterpolator;
import android.widget.AdapterView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import androidx.annotation.ColorInt;
import androidx.annotation.ColorRes;
import androidx.annotation.Nullable;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;

import com.kongzue.dialogx.DialogX;
import com.kongzue.dialogx.R;
import com.kongzue.dialogx.interfaces.BaseDialog;
import com.kongzue.dialogx.interfaces.BlurViewType;
import com.kongzue.dialogx.interfaces.DialogConvertViewInterface;
import com.kongzue.dialogx.interfaces.DialogLifecycleCallback;
import com.kongzue.dialogx.interfaces.DialogXAnimInterface;
import com.kongzue.dialogx.interfaces.DialogXRunnable;
import com.kongzue.dialogx.interfaces.DialogXStyle;
import com.kongzue.dialogx.interfaces.MenuItemLayoutRefreshCallback;
import com.kongzue.dialogx.interfaces.OnBackPressedListener;
import com.kongzue.dialogx.interfaces.OnBackgroundMaskClickListener;
import com.kongzue.dialogx.interfaces.OnBindView;
import com.kongzue.dialogx.interfaces.OnIconChangeCallBack;
import com.kongzue.dialogx.interfaces.OnMenuItemClickListener;
import com.kongzue.dialogx.util.DialogXViewLoc;
import com.kongzue.dialogx.util.ItemDivider;
import com.kongzue.dialogx.util.PopMenuArrayAdapter;
import com.kongzue.dialogx.util.TextInfo;
import com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout;
import com.kongzue.dialogx.util.views.MaxRelativeLayout;
import com.kongzue.dialogx.util.views.PopMenuListView;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author: Kongzue
 * @github: https://github.com/kongzue/
 * @homepage: http://kongzue.com/
 * @mail: myzcxhh@live.cn
 * @createTime: 2021/8/18 14:27
 */
public class PopMenu extends BaseDialog {

    public static long overrideEnterDuration = -1;
    public static long overrideExitDuration = -1;

    protected PopMenu me = this;
    protected boolean bkgInterceptTouch = true;
    protected OnBindView<PopMenu> onBindView;                               // 自定义布局
    protected DialogLifecycleCallback<PopMenu> dialogLifecycleCallback;     // 对话框生命周期
    protected OnBackgroundMaskClickListener<PopMenu> onBackgroundMaskClickListener;
    protected List<CharSequence> menuList;
    protected List<Integer> iconResIds;
    protected boolean autoTintIconInLightOrDarkMode = true;
    protected DialogImpl dialogImpl;
    protected WeakReference<View> baseViewWeakReference;
    protected boolean overlayBaseView = true;                               // 允许菜单覆盖在 baseView 上
    protected OnMenuItemClickListener<PopMenu> onMenuItemClickListener;
    protected OnIconChangeCallBack<PopMenu> onIconChangeCallBack;           // 设置图标
    protected int width = -1;                                               // 指定菜单宽度
    protected int height = -1;                                              // 指定菜单高度
    protected TextInfo menuTextInfo;
    protected boolean offScreen = false;                                    // 超出屏幕
    protected float backgroundRadius = DialogX.defaultPopMenuBackgroundRadius;
    protected DialogXAnimInterface<PopMenu> dialogXAnimImpl;
    protected OnBackPressedListener<PopMenu> onBackPressedListener;
    protected MenuItemLayoutRefreshCallback<PopMenu> menuMenuItemLayoutRefreshCallback;
    protected int pressedIndex = -1;
    protected Map<Integer, Boolean> menuUsability = new HashMap<Integer, Boolean>();
    protected ItemDivider itemDivider;

    protected int alignGravity = -1;                                        // 指定菜单相对 baseView 的位置

    // 记录 baseView 位置
    protected DialogXViewLoc baseViewLoc = new DialogXViewLoc();
    private int selectIndex;
    public boolean notCheckHash = false;
    public int lastHash = -1;

    public PopMenu() {
        super();
    }

    public PopMenu(View baseView, List<CharSequence> menuList) {
        this.menuList = new ArrayList<>();
        this.menuList.addAll(menuList);
        this.baseView(baseView);
    }

    public PopMenu(View baseView, CharSequence[] menuList) {
        this.menuList = new ArrayList<>();
        this.menuList.addAll(Arrays.asList(menuList));
        this.baseView(baseView);
    }

    public PopMenu(List<CharSequence> menuList) {
        this.menuList = new ArrayList<>();
        this.menuList.addAll(menuList);
    }

    public PopMenu(CharSequence... menuList) {
        this.menuList = new ArrayList<>();
        this.menuList.addAll(Arrays.asList(menuList));
    }

    public PopMenu(String... menuList) {
        this.menuList = new ArrayList<>();
        this.menuList.addAll(Arrays.asList(menuList));
    }

    public PopMenu(OnBindView<PopMenu> onBindView) {
        this.onBindView = onBindView;
    }

    public PopMenu(View baseView, OnBindView<PopMenu> onBindView) {
        this.baseView(baseView);
        this.onBindView = onBindView;
    }

    public PopMenu(View baseView, List<CharSequence> menuList, OnBindView<PopMenu> onBindView) {
        this.baseView(baseView);
        this.menuList = new ArrayList<>();
        this.menuList.addAll(menuList);
        this.onBindView = onBindView;
    }

    public PopMenu(View baseView, CharSequence[] menuList, OnBindView<PopMenu> onBindView) {
        this.baseView(baseView);
        this.menuList = new ArrayList<>();
        this.menuList.addAll(Arrays.asList(menuList));
        this.onBindView = onBindView;
    }

    public PopMenu(List<CharSequence> menuList, OnBindView<PopMenu> onBindView) {
        this.menuList = new ArrayList<>();
        this.menuList.addAll(menuList);
        this.onBindView = onBindView;
    }

    public PopMenu(CharSequence[] menuList, OnBindView<PopMenu> onBindView) {
        this.menuList = new ArrayList<>();
        this.menuList.addAll(Arrays.asList(menuList));
        this.onBindView = onBindView;
    }

    public static PopMenu build() {
        return new PopMenu();
    }

    public static PopMenu build(DialogXStyle style) {
        return new PopMenu().setStyle(style);
    }

    public static PopMenu show(CharSequence... menus) {
        PopMenu popMenu = new PopMenu(menus);
        popMenu.show();
        return popMenu;
    }

    public static PopMenu show(String... menus) {
        PopMenu popMenu = new PopMenu(menus);
        popMenu.show();
        return popMenu;
    }

    public static PopMenu show(List<CharSequence> menuList) {
        PopMenu popMenu = new PopMenu(menuList);
        popMenu.show();
        return popMenu;
    }

    public static PopMenu show(View baseView, CharSequence[] menus) {
        PopMenu popMenu = new PopMenu(baseView, menus);
        popMenu.show();
        return popMenu;
    }

    public static PopMenu show(View baseView, List<CharSequence> menuList) {
        PopMenu popMenu = new PopMenu(baseView, menuList);
        popMenu.show();
        return popMenu;
    }

    public static PopMenu show(View baseView, CharSequence[] menus, OnBindView<PopMenu> onBindView) {
        PopMenu popMenu = new PopMenu(baseView, menus, onBindView);
        popMenu.show();
        return popMenu;
    }

    public static PopMenu show(View baseView, List<CharSequence> menuList, OnBindView<PopMenu> onBindView) {
        PopMenu popMenu = new PopMenu(baseView, menuList, onBindView);
        popMenu.show();
        return popMenu;
    }

    public static PopMenu show(CharSequence[] menus, OnBindView<PopMenu> onBindView) {
        PopMenu popMenu = new PopMenu(menus, onBindView);
        popMenu.show();
        return popMenu;
    }

    public static PopMenu show(List<CharSequence> menuList, OnBindView<PopMenu> onBindView) {
        PopMenu popMenu = new PopMenu(menuList, onBindView);
        popMenu.show();
        return popMenu;
    }

    private ViewTreeObserver viewTreeObserver;
    private ViewTreeObserver.OnDrawListener baseViewDrawListener;

    public PopMenu show() {
        if (isHide && getDialogView() != null && isShow) {
            if (hideWithExitAnim && getDialogImpl() != null) {
                getDialogImpl().boxBody.clearAnimation();
                getDialogView().setVisibility(View.VISIBLE);
                getDialogImpl().boxRoot.animate().alpha(1f);
                getDialogImpl().getDialogXAnimImpl().doShowAnim(me, getDialogImpl().boxBody);
            } else {
                getDialogView().setVisibility(View.VISIBLE);
            }
            return this;
        }

        super.beforeShow();
        if (getDialogView() == null) {
            int layoutId = isLightTheme() ? R.layout.layout_dialogx_popmenu_material : R.layout.layout_dialogx_popmenu_material_dark;
            if (getStyle().popMenuSettings() != null) {
                if (getStyle().popMenuSettings().layout(isLightTheme()) != 0) {
                    layoutId = getStyle().popMenuSettings().layout(isLightTheme());
                }
            }
            layoutId = getCustomDialogLayoutResId(isLightTheme()) != 0 ? getCustomDialogLayoutResId(isLightTheme()) : layoutId;

            View dialogView = createView(layoutId);
            dialogImpl = new DialogImpl(dialogView);
            if (dialogView != null) {
                dialogView.setTag(me);
            }
            show(dialogView);
        } else {
            show(getDialogView());
        }
        if (baseView() != null) {
            viewTreeObserver = baseView().getViewTreeObserver();
            viewTreeObserver.addOnDrawListener(baseViewDrawListener = new ViewTreeObserver.OnDrawListener() {
                @Override
                public void onDraw() {
                    int[] baseViewLocCache = new int[2];
                    if (baseView() != null) {
                        baseView().getLocationInWindow(baseViewLocCache);
                        if (getDialogImpl() != null && !baseViewLoc.isSameLoc(baseViewLocCache) && baseView().getVisibility() == VISIBLE) {
                            baseViewLoc.set(baseViewLocCache);
                            refreshMenuLoc();
                        }
                    } else {
                        if (viewTreeObserver != null) {
                            removeDrawListener(viewTreeObserver, this);
                            viewTreeObserver = null;
                            baseViewDrawListener = null;
                        }
                    }
                }
            });
        }
        return this;
    }

    public PopMenu show(Activity activity) {
        if (isHide && getDialogView() != null && isShow) {
            if (hideWithExitAnim && getDialogImpl() != null) {
                getDialogImpl().boxBody.clearAnimation();
                getDialogView().setVisibility(View.VISIBLE);
                getDialogImpl().boxRoot.animate().alpha(1f);
                getDialogImpl().getDialogXAnimImpl().doShowAnim(me, getDialogImpl().boxBody);
            } else {
                getDialogView().setVisibility(View.VISIBLE);
            }
            return this;
        }

        super.beforeShow();
        if (getDialogView() == null) {
            int layoutId = isLightTheme() ? R.layout.layout_dialogx_popmenu_material : R.layout.layout_dialogx_popmenu_material_dark;
            if (getStyle().popMenuSettings() != null) {
                if (getStyle().popMenuSettings().layout(isLightTheme()) != 0) {
                    layoutId = getStyle().popMenuSettings().layout(isLightTheme());
                }
            }
            layoutId = getCustomDialogLayoutResId(isLightTheme()) != 0 ? getCustomDialogLayoutResId(isLightTheme()) : layoutId;

            View dialogView = createView(layoutId);
            dialogImpl = new DialogImpl(dialogView);
            if (dialogView != null) {
                dialogView.setTag(me);
            }
            show(activity, dialogView);
        } else {
            show(activity, getDialogView());
        }
        if (baseView() != null) {
            viewTreeObserver = baseView().getViewTreeObserver();
            viewTreeObserver.addOnDrawListener(baseViewDrawListener = new ViewTreeObserver.OnDrawListener() {
                @Override
                public void onDraw() {
                    int[] baseViewLocCache = new int[2];
                    if (baseView() != null) {
                        baseView().getLocationInWindow(baseViewLocCache);
                        if (getDialogImpl() != null && !baseViewLoc.isSameLoc(baseViewLocCache) && baseView().getVisibility() == VISIBLE) {
                            baseViewLoc.set(baseViewLocCache);
                            refreshMenuLoc();
                        }
                    } else {
                        if (viewTreeObserver != null) {
                            removeDrawListener(viewTreeObserver, this);
                            viewTreeObserver = null;
                            baseViewDrawListener = null;
                        }
                    }
                }
            });
        }
        return this;
    }

    private void refreshMenuLoc() {
        if (getDialogImpl() == null || getDialogImpl().boxRoot == null || baseView() == null) {
            return;
        }
        getDialogImpl().boxBody.setTag(null);
        DialogXViewLoc loc = getMenuLoc();
        getDialogImpl().boxBody.setTag(loc);
        if (!isEnterAnimRunning) {
            if (loc.getX() != getDialogImpl().boxBody.getX()) {
                getDialogImpl().boxBody.setX(loc.getX());
            }
            if (loc.getY() != getDialogImpl().boxBody.getY()) {
                getDialogImpl().boxBody.setY(loc.getY());
            }
        }
        if (getDialogImpl().boxBody.getWidth() != loc.getW()) {
            RelativeLayout.LayoutParams rLp = new RelativeLayout.LayoutParams((int) loc.getW(), ViewGroup.LayoutParams.WRAP_CONTENT);
            getDialogImpl().boxBody.setLayoutParams(rLp);
        }
    }

    protected DialogXViewLoc getMenuLoc() {
        if (getDialogImpl().boxBody.getTag() instanceof DialogXViewLoc) {
            return (DialogXViewLoc) getDialogImpl().boxBody.getTag();
        }
        DialogXViewLoc result = new DialogXViewLoc();

        MaxRelativeLayout boxBody = getDialogImpl().boxBody;
        DialogXBaseRelativeLayout boxRoot = getDialogImpl().boxRoot;
        // 菜单位置计算逻辑
        int baseViewLeft = (int) baseViewLoc.getX();
        int baseViewTop = (int) baseViewLoc.getY();
        int calX = 0, calY = 0;
        if (alignGravity != -1) {
            if (isAlignGravity(Gravity.CENTER_VERTICAL)) {
                calY = (Math.max(0, baseViewTop + baseView().getMeasuredHeight() / 2 - boxBody.getHeight() / 2));
            }
            if (isAlignGravity(Gravity.CENTER_HORIZONTAL)) {
                calX = (Math.max(0, baseViewLeft + (getWidth() > 0 ? baseView().getMeasuredWidth() / 2 - getWidth() / 2 : 0)));
            }
            if (isAlignGravity(Gravity.CENTER)) {
                calX = (Math.max(0, baseViewLeft + (getWidth() > 0 ? (baseView().getMeasuredWidth() / 2 - getWidth() / 2) : 0)));
                calY = (Math.max(0, baseViewTop + baseView().getMeasuredHeight() / 2 - boxBody.getHeight() / 2));
            }
            if (overlayBaseView) {
                // 菜单覆盖在 baseView 上时
                if (isAlignGravity(Gravity.TOP)) {
                    calY = (baseViewTop + baseView().getMeasuredHeight() - boxBody.getHeight());
                    if (calX == 0) {
                        calX = (Math.max(0, baseViewLeft + (getWidth() > 0 ? baseView().getMeasuredWidth() / 2 - getWidth() / 2 : 0)));
                    }
                }
                if (isAlignGravity(Gravity.LEFT)) {
                    calX = Math.max(0, (baseViewLeft + baseView().getMeasuredWidth() - boxBody.getWidth()));
                    if (calY == 0) {
                        calY = (Math.max(0, baseViewTop + baseView().getMeasuredHeight() / 2 - boxBody.getHeight() / 2));
                    }
                }
                if (isAlignGravity(Gravity.RIGHT)) {
                    calX = baseViewLeft;
                    if (calY == 0) {
                        calY = (Math.max(0, baseViewTop + baseView().getMeasuredHeight() / 2 - boxBody.getHeight() / 2));
                    }
                }
                if (isAlignGravity(Gravity.BOTTOM)) {
                    calY = baseViewTop;
                    if (calX == 0) {
                        calX = (Math.max(0, baseViewLeft + (getWidth() > 0 ? baseView().getMeasuredWidth() / 2 - getWidth() / 2 : 0)));
                    }
                }
            } else {
                if (isAlignGravity(Gravity.TOP)) {
                    calY = (Math.max(0, baseViewTop - boxBody.getHeight()));
                    if (calX == 0) {
                        calX = (Math.max(0, baseViewLeft + (getWidth() > 0 ? baseView().getMeasuredWidth() / 2 - getWidth() / 2 : 0)));
                    }
                }
                if (isAlignGravity(Gravity.LEFT)) {
                    calX = Math.max(0, (baseViewLeft - boxBody.getWidth()));
                    if (calY == 0) {
                        calY = (Math.max(0, baseViewTop + baseView().getMeasuredHeight() / 2 - boxBody.getHeight() / 2));
                    }
                }
                if (isAlignGravity(Gravity.RIGHT)) {
                    calX = (Math.max(0, baseViewLeft + baseView().getWidth()));
                    if (calY == 0) {
                        calY = (Math.max(0, baseViewTop + baseView().getMeasuredHeight() / 2 - boxBody.getHeight() / 2));
                    }
                }
                if (isAlignGravity(Gravity.BOTTOM)) {
                    calY = (Math.max(0, baseViewTop + baseView().getHeight()));
                    if (calX == 0) {
                        calX = (Math.max(0, baseViewLeft + (getWidth() > 0 ? baseView().getMeasuredWidth() / 2 - getWidth() / 2 : 0)));
                    }
                }
            }
            if (!offScreen) {
                if (calX < 0) {
                    calX = 0;
                }
                if ((calX + boxBody.getWidth()) > boxRoot.getUseAreaWidth()) {
                    calX = boxRoot.getUseAreaWidth() - boxBody.getWidth();
                }
                if (calY < 0) {
                    calY = 0;
                }
                if ((calY + boxBody.getHeight()) > boxRoot.getUseAreaHeight()) {
                    calY = boxRoot.getUseAreaHeight() - boxBody.getHeight();
                }
            }
            result.setX(calX).setY(calY);
        } else {
            int mHeight = PopMenu.this.height == -1 ? baseView().getHeight() : PopMenu.this.height;
            int left = (int) baseViewLoc.getX();
            int top = (int) (baseViewLoc.getY() + (overlayBaseView ? 0 : mHeight) + selectItemYDeviation);

            if (!offScreen) {
                if (left < 0) {
                    left = 0;
                }
                if ((left + boxBody.getWidth()) > boxRoot.getUseAreaWidth()) {
                    left = boxRoot.getUseAreaWidth() - boxBody.getWidth();
                }
                if (top < 0) {
                    top = 0;
                }
                if ((top + boxBody.getHeight()) > boxRoot.getUseAreaHeight()) {
                    top = boxRoot.getUseAreaHeight() - boxBody.getHeight();
                }
            }
            result.setX(left).setY(top);
        }

        int mWidth = PopMenu.this.width == -1 ? baseView().getWidth() : PopMenu.this.width;
        int mHeight = PopMenu.this.height == -1 ? baseView().getHeight() : PopMenu.this.height;
        result.setW(mWidth).setH(mHeight);
        return result;
    }

    protected PopMenuArrayAdapter menuListAdapter;
    protected int selectItemYDeviation; // 如果找到了选中菜单，这里记录的是其位置的 Y 偏差值
    protected boolean isEnterAnimRunning;

    public class DialogImpl implements DialogConvertViewInterface {

        private List<View> blurViews;

        public DialogXBaseRelativeLayout boxRoot;
        public MaxRelativeLayout boxBody;
        public RelativeLayout boxCustom;
        public PopMenuListView listMenu;

        public DialogImpl(View convertView) {
            if (convertView == null) return;
            setDialogView(convertView);
            boxRoot = convertView.findViewById(R.id.box_root);
            boxBody = convertView.findViewById(R.id.box_body);
            boxCustom = convertView.findViewById(R.id.box_custom);
            listMenu = convertView.findViewById(R.id.listMenu);
            boxBody.setVisibility(View.INVISIBLE);

            blurViews = findAllBlurView(convertView);

            // 先设置为 -1 表示未初始化位置
            boxBody.setX(-1);
            boxBody.setY(-1);
            init();
        }

        @Override
        public void init() {
            closing = false;
            if (menuListAdapter == null) {
                menuListAdapter = new PopMenuArrayAdapter(me, getOwnActivity(), menuList);
            }

            boxRoot.setParentDialog(me);
            boxRoot.setOnLifecycleCallBack(new DialogXBaseRelativeLayout.OnLifecycleCallBack() {
                @Override
                public void onShow() {
                    isShow = true;
                    preShow = false;
                    setLifecycleState(Lifecycle.State.CREATED);
                    onDialogShow();
                    getDialogLifecycleCallback().onShow(me);
                    PopMenu.this.onShow(me);
                    refreshUI();
                }

                @Override
                public void onDismiss() {
                    isShow = false;
                    getDialogLifecycleCallback().onDismiss(me);
                    PopMenu.this.onDismiss(me);
                    setLifecycleState(Lifecycle.State.DESTROYED);
                    menuListAdapter = null;
                    dialogImpl = null;
                    baseView(null);
                    dialogLifecycleCallback = null;
                    BaseDialog.gc();
                }
            });

            boxRoot.setOnBackPressedListener(new DialogXBaseRelativeLayout.PrivateBackPressedListener() {
                @Override
                public boolean onBackPressed() {
                    if (onBackPressedListener != null) {
                        if (onBackPressedListener.onBackPressed(me)) {
                            dismiss();
                        }
                    } else {
                        if (isCancelable()) {
                            dismiss();
                        }
                    }
                    return true;
                }
            });
            listMenu.setMaxHeight(getRootFrameLayout() == null ? dip2px(500) : getRootFrameLayout().getMeasuredHeight() - dip2px(150));

            boxBody.setVisibility(View.INVISIBLE);
            boxBody.post(new Runnable() {

                @Override
                public void run() {
                    getDialogXAnimImpl().doShowAnim(me, boxBody);
                    setLifecycleState(Lifecycle.State.RESUMED);

                    Integer blurFrontColor = null;
                    Float dialogXRadius = null;
                    if (style.popMenuSettings() != null && style.popMenuSettings().blurBackgroundSettings() != null) {
                        blurFrontColor = getColorNullable(getIntStyleAttr(style.popMenuSettings().blurBackgroundSettings().blurForwardColorRes(isLightTheme())));
                        dialogXRadius = getFloatStyleAttr((float) style.popMenuSettings().blurBackgroundSettings().blurBackgroundRoundRadiusPx());
                    }

                    if (blurViews != null) {
                        for (View blurView : blurViews) {
                            ((BlurViewType) blurView).setOverlayColor(backgroundColor == null ? blurFrontColor : backgroundColor);
                            ((BlurViewType) blurView).setRadiusPx(dialogXRadius);
                        }
                    }
                }
            });

            int dividerDrawableResId = 0;
            int dividerHeight = 0;
            if (style.popMenuSettings() != null) {
                dividerDrawableResId = style.popMenuSettings().overrideMenuDividerDrawableRes(isLightTheme());
                dividerHeight = style.popMenuSettings().overrideMenuDividerHeight(isLightTheme());
            }
            if (dividerDrawableResId == 0) {
                dividerDrawableResId = isLightTheme() ? R.drawable.rect_dialogx_material_menu_split_divider : R.drawable.rect_dialogx_material_menu_split_divider_night;
            }

            listMenu.setOverScrollMode(OVER_SCROLL_NEVER);
            listMenu.setVerticalScrollBarEnabled(false);
            listMenu.setDivider(getResources().getDrawable(dividerDrawableResId));
            listMenu.setDividerHeight(dividerHeight);

            listMenu.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    if (!isMenuItemEnable(position)) {
                        return;
                    }
                    haptic(view);
                    selectIndex = position;
                    if (!closing) {
                        lastHash = menuList.hashCode();
                        boolean callBack = getOnMenuItemClickListener().onClick(me, menuList.get(position), position);
                        if (!notCheckHash) {
                            if (lastHash == menuList.hashCode()) {
                                if (callBack) {
                                    callBack = false;
                                }
                            }
                        }
                        if (!callBack) {
                            dismiss();
                        }
                    }
                }
            });
            onDialogInit();
        }

        @Override
        public void refreshView() {
            if (boxRoot == null || getOwnActivity() == null) {
                return;
            }
            boxRoot.setAutoUnsafePlacePadding(isEnableImmersiveMode());
            boxRoot.setRootPadding(screenPaddings[0], screenPaddings[1], screenPaddings[2], screenPaddings[3]);
            if (listMenu.getAdapter() == null) {
                listMenu.setAdapter(menuListAdapter);
            } else {
                if (menuListAdapter.getMenuList() != menuList) {
                    menuListAdapter = new PopMenuArrayAdapter(me, getOwnActivity(), menuList);
                    listMenu.setAdapter(menuListAdapter);
                } else {
                    menuListAdapter.notifyDataSetChanged();
                }
            }

            if (bkgInterceptTouch) {
                if (isCancelable()) {
                    boxRoot.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            if (onBackgroundMaskClickListener == null || !onBackgroundMaskClickListener.onClick(me, v)) {
                                doDismiss(v);
                            }
                        }
                    });
                } else {
                    boxRoot.setOnClickListener(null);
                }
            } else {
                boxRoot.setClickable(false);
            }
            if (backgroundColor != null) {
                tintColor(boxBody, backgroundColor);
            }

            if (backgroundRadius > -1) {
                if (boxBody.getBackground() instanceof GradientDrawable) {
                    GradientDrawable gradientDrawable = (GradientDrawable) boxBody.getBackground();
                    if (gradientDrawable != null)
                        gradientDrawable.setCornerRadius(backgroundRadius);
                }
                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
                    boxBody.setOutlineProvider(new ViewOutlineProvider() {
                        @Override
                        public void getOutline(View view, Outline outline) {
                            outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), backgroundRadius);
                        }
                    });
                    boxBody.setClipToOutline(true);
                }

                if (blurViews != null) {
                    for (View blurView : blurViews) {
                        ((BlurViewType) blurView).setRadiusPx(backgroundRadius);
                    }
                }
            }

            if (onBindView != null && onBindView.getCustomView() != null) {
                onBindView.bindParent(boxCustom, me);
                boxCustom.setVisibility(View.VISIBLE);
            } else {
                boxCustom.setVisibility(View.GONE);
            }

            if (width != -1) {
                boxBody.setMaxWidth(width);
                boxBody.setMinimumWidth(width);
            }

            if (height != -1) {
                boxBody.setMaxHeight(height);
                boxBody.setMinimumHeight(height);
            }

            if (backgroundColor != null) {
                tintColor(boxBody, backgroundColor);

                if (blurViews != null) {
                    for (View blurView : blurViews) {
                        ((BlurViewType) blurView).setOverlayColor(backgroundColor);
                    }
                }
            }

            if (itemDivider != null) {
                listMenu.setDivider(itemDivider.createDividerDrawable(getOwnActivity(), isLightTheme()));
                listMenu.setDividerHeight(itemDivider.getWidth());
            }

            onDialogRefreshUI();
        }

        @Override
        public void doDismiss(View v) {
            if (preDismiss(PopMenu.this)) {
                return;
            }
            if (v != null) {
                v.setEnabled(false);
            }

            if (!dismissAnimFlag && boxRoot != null) {
                dismissAnimFlag = true;
                boxRoot.post(new Runnable() {
                    @Override
                    public void run() {
                        getDialogXAnimImpl().doExitAnim(me, boxBody);

                        runOnMainDelay(new Runnable() {
                            @Override
                            public void run() {
                                if (baseViewDrawListener != null) {
                                    if (viewTreeObserver != null) {
                                        removeDrawListener(viewTreeObserver, baseViewDrawListener);
                                    } else {
                                        if (baseView() != null) {
                                            removeDrawListener(baseView().getViewTreeObserver(), baseViewDrawListener);
                                        }
                                    }
                                    baseViewDrawListener = null;
                                    viewTreeObserver = null;
                                }
                                dismiss(getDialogView());
                            }
                        }, getExitAnimationDuration(null));
                    }
                });
            }
        }

        protected DialogXAnimInterface<PopMenu> getDialogXAnimImpl() {
            if (dialogXAnimImpl == null) {
                dialogXAnimImpl = new DialogXAnimInterface<PopMenu>() {

                    int selectMenuIndex = -1;

                    @Override
                    public void doShowAnim(PopMenu dialog, ViewGroup dialogBodyView) {
                        long enterAnimDurationTemp = getEnterAnimationDuration(null);

                        if (baseView() != null) {
