package com.github.huajianjiang.expandablerecyclerview.sample;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import com.github.huajianjiang.expandablerecyclerview.sample.adapter.MyAdapter;
import com.github.huajianjiang.expandablerecyclerview.sample.anim.CircularRevealItemAnimator;
import com.github.huajianjiang.expandablerecyclerview.sample.model.MyParent;
import com.github.huajianjiang.expandablerecyclerview.sample.util.AppUtil;
import com.github.huajianjiang.expandablerecyclerview.util.Logger;
import com.github.huajianjiang.expandablerecyclerview.widget.ExpandableAdapter;
import com.github.huajianjiang.expandablerecyclerview.widget.ExpandableRecyclerView;
import com.github.huajianjiang.expandablerecyclerview.widget.ParentViewHolder;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import static com.github.huajianjiang.expandablerecyclerview.sample.SingleRvFragment.KEY_DATA;
import static com.github.huajianjiang.expandablerecyclerview.sample.SingleRvFragment.REQUEST_RESULT;

/**
 * @author HuaJian Jiang.
 *         Date 2017/1/23.
 */
public class MultipleRvFragment extends Fragment {
    private static final String TAG = MultipleRvFragment.class.getSimpleName();
    private MyAdapter mAdapter;
    private RecyclerView.ItemAnimator mItemAnimator;
    private PresenterImpl mIPresenter;
    private ArrayList<MyParent> mData;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
        setRetainInstance(true);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
            @Nullable Bundle savedInstanceState)
    {
        return inflater.inflate(R.layout.fragment_multiple_rv, container, false);
    }


    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // 保存 ExpandableRecyclerView 状态
        if (savedInstanceState != null) {
            Logger.e(TAG, "<<<<<<<<<<<<<<<<<< Restore Data >>>>>>>>>>>>>>>>>");
            mData = savedInstanceState.getParcelableArrayList(KEY_DATA);
        } else {
            mData = AppUtil.getListData();
        }
        init(getView());
        mAdapter.onRestoreInstanceState(savedInstanceState);
    }

    private void init(View rootView) {
        mAdapter = new MyAdapter(getActivity(), mData);
        mAdapter.setExpandCollapseMode(ExpandableAdapter.ExpandCollapseMode.MODE_DEFAULT);
        mAdapter.addParentExpandableStateChangeListener(new ParentExpandableStateChangeListener());
        mAdapter.addParentExpandCollapseListener(new ParentExpandCollapseListener());

        RecyclerView rv_top= (RecyclerView) rootView.findViewById(R.id.rv_top);
        rv_top.setAdapter(mAdapter);
        rv_top.addItemDecoration(mAdapter.getItemDecoration());
        mItemAnimator =
                AppUtil.checkLollipop() ? new CircularRevealItemAnimator() : new DefaultItemAnimator();
        rv_top.setItemAnimator(mItemAnimator);

        RecyclerView rv_bottom = (RecyclerView) rootView.findViewById(R.id.rv_bottom);
        rv_bottom.setAdapter(mAdapter);
        rv_bottom.addItemDecoration(mAdapter.getItemDecoration());

        mIPresenter = new PresenterImpl(mAdapter, mData);

        registerForContextMenu(rv_top);
        registerForContextMenu(rv_bottom);
    }

    private class ParentExpandableStateChangeListener
            implements ExpandableAdapter.OnParentExpandableStateChangeListener
    {
        @Override
        public void onParentExpandableStateChanged(RecyclerView rv, ParentViewHolder pvh,
                int position, boolean expandable)
        {
            Logger.e(TAG, "onParentExpandableStateChanged=" + position + "," + rv.getTag());
            if (pvh == null) return;
            ImageView arrow = pvh.getView(R.id.arrow);
            if (expandable && arrow.getVisibility() != View.VISIBLE) {
                arrow.setVisibility(View.VISIBLE);
                arrow.setRotation(pvh.isExpanded() ? 180 : 0);
            } else if (!expandable && arrow.getVisibility() == View.VISIBLE) {
                arrow.setVisibility(View.GONE);
            }
        }
    }

    private class ParentExpandCollapseListener
            implements ExpandableAdapter.OnParentExpandCollapseListener
    {
        @Override
        public void onParentExpanded(RecyclerView rv, ParentViewHolder pvh, int position,
                boolean pendingCause, boolean byUser)
        {
            Logger.e(TAG, "onParentExpanded=" + position + "," + rv.getTag() + ",byUser=" + byUser);
            if (pvh == null) return;
            ImageView arrow = pvh.getView(R.id.arrow);
            if (arrow.getVisibility() != View.VISIBLE) return;
            float currRotate = arrow.getRotation();
            //重置为从0开始旋转
            if (currRotate == 360) {
                arrow.setRotation(0);
            }
            if (pendingCause) {
                arrow.setRotation(180);
            } else {
                arrow.animate()
                     .rotation(180)
                     .setDuration(mItemAnimator.getAddDuration() + 180)
                     .start();
            }
        }

        @Override
        public void onParentCollapsed(RecyclerView rv, ParentViewHolder pvh, int position,
                boolean pendingCause, boolean byUser)
        {
            Logger.e(TAG,
                    "onParentCollapsed=" + position + ",tag=" + rv.getTag() + ",byUser=" + byUser);

            if (pvh == null) return;
            final ImageView arrow = pvh.getView(R.id.arrow);
            if (arrow.getVisibility() != View.VISIBLE) return;
            final float currRotate = arrow.getRotation();
            float rotate = 360;
            //未展开完全并且当前旋转角度小于180,逆转回去
            if (currRotate < 180) {
                rotate = 0;
            }
            if (pendingCause) {
                arrow.setRotation(rotate);
            } else {
                arrow.animate().rotation(rotate)
                        .setDuration(mItemAnimator.getRemoveDuration() + 180).start();
            }
        }
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo)
    {
        getActivity().getMenuInflater().inflate(R.menu.menu_main, menu);
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        ExpandableRecyclerView.ExpandableRecyclerViewContextMenuInfo menuInfo =
                (ExpandableRecyclerView.ExpandableRecyclerViewContextMenuInfo) item.getMenuInfo();
        Logger.e(TAG, menuInfo.toString());
        return true;
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.menu_main, menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        switch (id) {
            case  R.id.action_test:
                DialogFragment dialog = (DialogFragment) getChildFragmentManager()
                        .findFragmentByTag("dialog");
                if (dialog == null) dialog = new MyDialog();
                dialog.setTargetFragment(this, REQUEST_RESULT);
                dialog.show(getChildFragmentManager(), "dialog");
                break;
            case R.id.action_refresh:
                mAdapter.notifyAllChanged();
                break;
            case R.id.action_toggle_expandable_1:
                mAdapter.toggleExpandable(1);
                break;
            case R.id.action_expand_all:
                mAdapter.expandAllParents();
                break;
            case R.id.action_collapse_all:
                mAdapter.collapseAllParents();
                break;
            case R.id.action_expand_1:
                mAdapter.expandParent(1);
                break;
            case R.id.action_collapse_1:
                mAdapter.collapseParent(1);
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode != Activity.RESULT_OK) return;
        if (requestCode == REQUEST_RESULT) {
            ArrayList<String> requests = data.getStringArrayListExtra(MyDialog.REQUEST);
            Log.e(TAG, "requests=" + requests.toString());
            final int requestCount = requests.size();
            for (int i = 0; i < requestCount; i++) {
                String request = requests.get(i);
                String[] requestSplit = request.split(",");
                String method = requestSplit[0];
                final int argsCount = requestSplit.length - 1;
                try {
                    Object[] args = new Object[argsCount];
                    Class<?>[] argTypes = new Class<?>[argsCount];
                    for (int k = 0; k < argsCount; k++) {
                        argTypes[k] = int.class;
                        try {
                            args[k] = Integer.valueOf(requestSplit[k + 1]);
                        } catch (NumberFormatException e) {
                            AppUtil.showToast(getContext(), "Test failed,please check input format");
                            return;
                        }
                    }
                    Method m = IPresenter.class.getDeclaredMethod(method, argTypes);
                    Log.e(TAG, "method=" + m.toString());
                    m.setAccessible(true);
                    m.invoke(mIPresenter,args);
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                    AppUtil.showToast(getContext(), "Test failed,please check input format");
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                    AppUtil.showToast(getContext(), "Test failed,please check input format");
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                    AppUtil.showToast(getContext(), "Test failed,please check input format");
                }
            }
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Logger.e(TAG, "<<<<<<<<<<<<<<<<<< Save Data >>>>>>>>>>>>>>>>>");
        outState.putParcelableArrayList(KEY_DATA, mData);
        mAdapter.onSaveInstanceState(outState);
    }
}