/*
 * Copyright 2017 simplezhli
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.github.zl.changetablayout;

import android.content.Context;
import android.content.res.TypedArray;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.VerticalViewPager;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;

import static com.github.zl.changetablayout.Constant.ARRAY_INITIAL_VALUE;

/**
 * 作者:weilu on 2017/3/15 13:59
 */

public class ChangeTabLayout extends ScrollView{

    /**
     * tab收起与展开
     */
    private boolean tabLayoutState = true;
    /**
     * tabLayout是否可以点击
     */
    private boolean tabLayoutIsClick = true;
    /**
     * tabView切换是否需要文字实时变化
     */
    private boolean flag = false;
    private final int tabViewHeight;
    private final int tabImageHeight;
    private final int defaultTabImageColor;
    private final int selectedTabImageColor;
    private float textSize;
    private int indicatorPadding;
    private int defaultTabTextColor;
    private int selectedTabTextColor;

    private VerticalViewPager viewPager;
    private final ChangeTabStrip tabStrip;

    private OnTabClickListener onTabClickListener;
    private InternalTabClickListener internalTabClickListener;

    private float density = 0;
    private int page = 0; //当前页数位置

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

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

    public ChangeTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //禁用滚动条
        setVerticalScrollBarEnabled(false);
        //去除阴影
        setOverScrollMode(OVER_SCROLL_NEVER);
        //防止ScrollView子View不能撑满全屏显示问题
        setFillViewport(true);

        final DisplayMetrics dm = getResources().getDisplayMetrics();
        density = dm.density;

        int tabViewHeight = (int) (Constant.TAB_VIEW_HEIGHT * density);
        int tabImageHeight = (int) (Constant.TAB_IMAGE_HEIGHT * density);
        int defaultTabImageColor = Constant.GRAY;
        int selectedTabImageColor = Constant.RED;
        int indicatorPadding = (int) (Constant.SELECTED_INDICATOR_PADDING_DIPS * density);
        float textSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, Constant.TAB_VIEW_TEXT_SIZE_SP, dm);
        int defaultTabTextColor = Constant.GRAY;
        int selectedTabTextColor = Constant.WHITE;

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ChangeTabLayout);
        tabViewHeight = a.getDimensionPixelSize(R.styleable.ChangeTabLayout_ctl_tabViewHeight, tabViewHeight);
        tabImageHeight = a.getDimensionPixelSize(R.styleable.ChangeTabLayout_ctl_tabImageHeight, tabImageHeight);
        defaultTabImageColor = a.getColor(R.styleable.ChangeTabLayout_ctl_defaultTabImageColor, defaultTabImageColor);
        selectedTabImageColor = a.getColor(R.styleable.ChangeTabLayout_ctl_selectedTabImageColor, selectedTabImageColor);
        textSize = a.getDimension(R.styleable.ChangeTabLayout_ctl_defaultTabTextSize, textSize);
        defaultTabTextColor = a.getColor(R.styleable.ChangeTabLayout_ctl_defaultTabTextColor, defaultTabTextColor);
        selectedTabTextColor = a.getColor(R.styleable.ChangeTabLayout_ctl_selectedTabTextColor, selectedTabTextColor);
        indicatorPadding = a.getDimensionPixelSize(R.styleable.ChangeTabLayout_ctl_indicatorPadding, indicatorPadding);
        a.recycle();

        this.tabViewHeight = tabViewHeight;
        this.tabImageHeight = tabImageHeight;
        this.defaultTabImageColor = defaultTabImageColor;
        this.selectedTabImageColor = selectedTabImageColor;
        this.textSize = textSize;
        this.indicatorPadding = indicatorPadding;
        this.defaultTabTextColor = defaultTabTextColor;
        this.selectedTabTextColor = selectedTabTextColor;

        this.tabStrip = new ChangeTabStrip(context, attrs);
        this.internalTabClickListener = new InternalTabClickListener();

        addView(tabStrip, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    }

    private int [] icon;
    private int [] iconSelected;
    private int[] lastPosition; //水平ViewPages position位置
    private float[] lastValue; //水平ViewPages positionOffset位置

    public void setViewPager(VerticalViewPager viewPager, int [] iconDefault, int [] iconSelected) {
        tabStrip.removeAllViews();

        this.viewPager = viewPager;
        this.icon = iconDefault;
        this.iconSelected = iconSelected;
        page = 0;
        if (viewPager != null && viewPager.getAdapter() != null) {
            viewPager.addOnPageChangeListener(new InternalViewPagerListener());
            viewPager.setOnTouchListener(new ViewPagerTouchListener());
            lastPosition = new int[viewPager.getAdapter().getCount()];
            lastValue = new float[viewPager.getAdapter().getCount()];
            if(icon != null){
                populateTabStrip();
            }
        }
    }

    private void populateTabStrip() {
        final PagerAdapter adapter = viewPager.getAdapter();

        if(adapter.getCount() != icon.length){
            return;
        }

        if(iconSelected != null && iconSelected.length != icon.length){
            return;
        }

        int size = adapter.getCount();
        for (int i = 0; i < size; i++) {
            LinearLayout tabView;
            if(iconSelected == null){
                tabView = createTabView(adapter.getPageTitle(i), icon[i], 0);
            }else{
                tabView = createTabView(adapter.getPageTitle(i), icon[i], iconSelected[i]);
            }

            if (tabView == null) {
                throw new IllegalStateException("tabView is null.");
            }

            if (internalTabClickListener != null) {
                //分别为图片与文字设置点击事件,为了收起状态时文字不能点击做准备
                tabView.getChildAt(0).setOnClickListener(internalTabClickListener);
                tabView.getChildAt(1).setOnClickListener(internalTabClickListener);
            }

            tabStrip.addView(tabView);

            if (i == viewPager.getCurrentItem()) {
                ChangeTextView textView = (ChangeTextView) tabView.getChildAt(1);
                textView.setLevel(5000);
            }

            lastPosition[i] = ARRAY_INITIAL_VALUE;
        }
        setTabLayoutState(true); //默认设置为打开状态
    }

    protected LinearLayout createTabView(CharSequence title, int icon, int selectIcon) {

        LinearLayout mLinearLayout = new LinearLayout(getContext());
        mLinearLayout.setOrientation(LinearLayout.HORIZONTAL);
        mLinearLayout.setGravity(Gravity.CENTER_VERTICAL);
        mLinearLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, tabViewHeight));

        ImageView imageView = new ImageView(getContext());
        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(tabImageHeight + (int) (16 * density), tabViewHeight);
        imageView.setPadding((int) (9 * density), 0, (int) (7 * density), 0);
        imageView.setLayoutParams(lp);

        RevealDrawable drawable;

        if(selectIcon != 0){
            drawable = new RevealDrawable(DrawableUtils.getDrawable(getContext(), icon), DrawableUtils.getDrawable(getContext(), selectIcon), RevealDrawable.VERTICAL);
        }else{
            drawable = new RevealDrawable(DrawableUtils.getTabDrawable(getContext(), icon, defaultTabImageColor),
                    DrawableUtils.getTabDrawable(getContext(), icon, selectedTabImageColor), RevealDrawable.VERTICAL);
        }

        imageView.setImageDrawable(drawable);

        ChangeTextView textView = new ChangeTextView(getContext());
        textView.setDefaultTabTextColor(defaultTabTextColor);
        textView.setSelectedTabTextColor(selectedTabTextColor);
        textView.setIndicatorPadding(indicatorPadding);
        textView.setTabViewTextSize(textSize);
        textView.setText(title.toString());
        textView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));

        mLinearLayout.addView(imageView);
        mLinearLayout.addView(textView);
        return mLinearLayout;
    }

    private class InternalViewPagerListener implements VerticalViewPager.OnPageChangeListener {

        private int scrollState;

        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            int tabStripChildCount = tabStrip.getChildCount();
            if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) {
                return;
            }
            tabStrip.onViewPagerPageChanged(position, positionOffset);
            scrollToTab(position, positionOffset);
        }

        @Override
        public void onPageScrollStateChanged(int state) {
            scrollState = state;
        }

        @Override
        public void onPageSelected(int position) {
            if (scrollState == ViewPager.SCROLL_STATE_IDLE) {
                scrollToTab(position, 0);
            }
            page = position; // 记录位置

            for (int i = 0, size = tabStrip.getChildCount(); i < size; i++) {
                ChangeTextView textView = (ChangeTextView) ((LinearLayout) tabStrip.getChildAt(i)).getChildAt(1);
                if (position == i) {
                    textView.setLevel(5000);
                }else {
                    textView.setLevel(0);
                }
            }
        }
    }

    private class ViewPagerTouchListener implements OnTouchListener{

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_MOVE:
                    flag = true;
                    break;
            }
            return false;
        }
    }

    private void scrollToTab(int tabIndex, float positionOffset) {

        final int tabStripChildCount = tabStrip.getChildCount();
        if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) {
            return;
        }

        LinearLayout selectedTab = (LinearLayout) getTabAt(tabIndex);

        if (0f <= positionOffset && positionOffset < 1f) {
            if(!tabLayoutState){
                ImageView imageView = (ImageView) selectedTab.getChildAt(0);
                ((RevealDrawable)imageView.getDrawable()).setOrientation(RevealDrawable.VERTICAL);
                imageView.setImageLevel((int) (positionOffset * 5000 + 5000));
            }
            if(flag){
                ChangeTextView textView = (ChangeTextView) selectedTab.getChildAt(1);
                textView.setLevel((int) (positionOffset * 5000 + 5000));
            }
        }

        if(!(tabIndex + 1 >= tabStripChildCount)){
            LinearLayout tab = (LinearLayout) getTabAt(tabIndex + 1);

            if(!tabLayoutState){
                ImageView img = (ImageView) tab.getChildAt(0);
                ((RevealDrawable)img.getDrawable()).setOrientation(RevealDrawable.VERTICAL);
                img.setImageLevel((int) (positionOffset * 5000));
            }
            if(flag){
                ChangeTextView text = (ChangeTextView) tab.getChildAt(1);
                text.setLevel((int) (positionOffset * 5000));
            }
        }

        int titleOffset = tabViewHeight * 2;
        int extraOffset = (int) (positionOffset * selectedTab.getHeight());

        int y = (tabIndex > 0 || positionOffset > 0) ? -titleOffset : 0;
        int start = selectedTab.getTop();
        y += start + extraOffset;

        scrollTo(0, y);
    }

    /**
     * 水平VIewPager控制
     */
    public void setPageScrolled(int p, int position, float positionOffset) {
        if (page != p){
            return;
        }
        //竖屏状态下`ViewPage`的`onPageScrolled`监听不正常修复(统一数据)
        if (positionOffset > 0.99 && positionOffset < 1){
            positionOffset = 0;
            position = position + 1;
        }else if (positionOffset < 0.01 && positionOffset > 0.00001){
            positionOffset = 0;
        }

        if (position - lastPosition[page] > 0) {
            if (lastPosition[page] != ARRAY_INITIAL_VALUE){
                tabLayoutState = false; //每次向左滑动结束时,进入判断,菜单关闭状态
                tabLayoutIsClick = true;
            }
        }else if(position - lastPosition[page] < 0){
            if(lastValue[page] - positionOffset < 0){
                //向左滑动时,不操作。
                return;
            }
        }

        lastPosition[page] = position;
        lastValue[page] = positionOffset;

        if(positionOffset == 0){
            return;
        }

        if(tabLayoutState){ //防止重复收起
            final int tabStripChildCount = tabStrip.getChildCount();
            if (tabStripChildCount == 0 || page < 0 || page >= tabStripChildCount) {
                return;
            }

            LinearLayout selectedTab = (LinearLayout) getTabAt(page);
            ImageView imageView = (ImageView) selectedTab.getChildAt(0);
            ((RevealDrawable)imageView.getDrawable()).setOrientation(RevealDrawable.HORIZONTAL);
            if (0f < positionOffset && positionOffset <= 1f) {
                imageView.setImageLevel((int) ((1 - positionOffset) * 5000 + 5000));
            }

            for (int i = 0, size = tabStrip.getChildCount(); i < size; i++) {
                ChangeTextView textView = (ChangeTextView) ((LinearLayout) tabStrip.getChildAt(i)).getChildAt(1);
                if (0f < positionOffset && positionOffset <= 1f) {
                    textView.setAlpha((1 - positionOffset));
                    if(positionOffset > 0.9f){
                        textView.setVisibility(INVISIBLE);
                        tabLayoutIsClick = false; //防止同时点击,导致状态混乱
                    }else{
                        textView.setVisibility(VISIBLE);
                        tabLayoutIsClick = true;
                    }
                }
            }

            if (positionOffset > 0.98){
                positionOffset = 1;
            }
            tabStrip.onViewPagerPageChanged(positionOffset);
        }
    }

    /**
     * 点击事件
     */
    private class InternalTabClickListener implements OnClickListener {
        @Override
        public void onClick(View v) {

            if(!tabLayoutState){ // 收起状态点击,切换为打开状态
                setTabLayoutState(true);
                return;
            }

            if(!tabLayoutIsClick){ //只阻止打开状态时点击
                return;
            }

            for (int i = 0, size = tabStrip.getChildCount(); i < size; i++) {
                if (v.getParent() == tabStrip.getChildAt(i)) {

                    viewPager.setCurrentItem(i);
                    flag = false;
//                    viewPager.setCurrentItem(i, false);
                    if (onTabClickListener != null) {
                        onTabClickListener.onTabClicked(i);
                    }
                }
            }
        }
    }

    /**
     * 返回指定位置的选项卡.
     * @param position 位置
     * @return 指定位置的选项卡View
     */
    public View getTabAt(int position) {
        return tabStrip.getChildAt(position);
    }

    public interface OnTabClickListener {

        void onTabClicked(int position);

    }

    /**
     * Tab点击事件{@link OnTabClickListener}
     * @param listener 点击事件监听器
     */
    public void setOnTabClickListener(OnTabClickListener listener) {
        onTabClickListener = listener;
    }

    /**
     * 获取TabLayout的状态
     */
    public boolean getTabLayoutState(){
        return tabLayoutState;
    }

    /**
     * 设置TabLayoutState
     * @param state 状态
     */
    public void setTabLayoutState(boolean state){
        tabLayoutState = true; //先设为可操作
        if(state){
            setPageScrolled(page, lastPosition[page], 0.00001f);
        }else{
            setPageScrolled(page, lastPosition[page], 1f);
        }
        tabLayoutState = state;
    }

    /**
     * 设置阴影颜色
     * @param shadowColor 阴影颜色
     */
    public void setShadowColor(int shadowColor){
        tabStrip.setShadowColor(shadowColor);
    }

    /**
     * 设置背景颜色
     * @param backgroundColor 背景颜色
     */
    public void setTabLayoutBackgroundColor(int backgroundColor){
        tabStrip.setTabLayoutBackgroundColor(backgroundColor);
    }

    /**
     * 设置指示器颜色
     * @param indicatorColor 指示器颜色
     */
    public void setIndicatorColor(int indicatorColor){
        tabStrip.setIndicatorColor(indicatorColor);
    }

    /**
     * 设置指示器标记颜色
     * @param leftBorderColor 指示器标记颜色
     */
    public void setLeftBorderColor(int leftBorderColor){
        tabStrip.setLeftBorderColor(leftBorderColor);
    }

    /**
     * 设置指示器上下内边距
     * @param indicatorPadding 指示器上下内边距
     */
    public void setIndicatorPadding(int indicatorPadding){
        tabStrip.setIndicatorPadding(indicatorPadding);
    }

    /**
     * 设置指示器标记宽度
     * @param leftBorderThickness 指示器标记宽度
     */
    public void setLeftBorderThickness(int leftBorderThickness){
        tabStrip.setLeftBorderThickness(leftBorderThickness);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(tabLayoutState){
            return super.onTouchEvent(event);
        }else {
            final int action = event.getAction();
            switch (action) {
                case MotionEvent.ACTION_DOWN: //收起时点击不拦截,传入下层
                    return false;
                case MotionEvent.ACTION_MOVE: //收起时,滑动文字部分拦截
                    if(tabImageHeight + (int) (20 * density) < event.getRawX()){
                        return true;
                    }
                    break;
            }
            return super.onTouchEvent(event);
        }
    }
}