package edu_cn.pku.course.fragments;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.view.animation.LayoutAnimationController;
import android.widget.LinearLayout;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;

import edu_cn.pku.course.Utils;
import edu_cn.pku.course.activities.R;
import edu_cn.pku.course.adapter.AnnouncementListRecyclerViewAdapter;


public class AnnouncementListFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {

    private AnnouncementLoadingTask mLoadingTask = null;
    private RecyclerView mRecyclerView;
    private SwipeRefreshLayout mAnnouncementListSwipeContainer;
    private AnnouncementListRecyclerViewAdapter adapter;

    public AnnouncementListFragment() {
        // Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of
     *
     * @return A new instance of fragment CoursesListFragment.
     */
    public static AnnouncementListFragment newInstance() {
        AnnouncementListFragment fragment = new AnnouncementListFragment();
        Bundle args = new Bundle();
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        LinearLayout linearLayout = (LinearLayout) inflater.inflate(R.layout.fragment_announcement_list, container, false);
        // 查找xml文件中的对象并保存进Java变量
        mRecyclerView = linearLayout.findViewById(R.id.recycler_announcement_list);
        mAnnouncementListSwipeContainer = linearLayout.findViewById(R.id.announcement_swipe_container);

        // 设置动画
        LayoutAnimationController animation = AnimationUtils.loadLayoutAnimation(getContext(), R.anim.layout_animation_fall_down);
        mAnnouncementListSwipeContainer.setLayoutAnimation(animation);
        // 设置刷新的监听类为此类(监听函数onRefresh)
        mAnnouncementListSwipeContainer.setOnRefreshListener(this);
        mAnnouncementListSwipeContainer.setColorSchemeColors(getResources().getColor(R.color.colorPrimary), getResources().getColor(R.color.colorAccent));

        FragmentActivity fa = getActivity();
        // 为了消除编译器Warning,需要判断一下是不是null,其实这基本上不可能出现null
        if (fa == null) {
            return linearLayout;
        }
        // 将读取已置顶课程列表的SharedPreferences传递给CourseListRecyclerViewAdapter
        // SharedPreferences sharedPreferences = fa.getSharedPreferences("pinnedAnnouncementList", Context.MODE_PRIVATE);
        adapter = new AnnouncementListRecyclerViewAdapter(new ArrayList<AnnouncementInfo>(), this);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
        mRecyclerView.setAdapter(adapter);

        try {
            String cachedList = getCachedAnnouncementsList();
            if (cachedList == null)
                throw new Exception();
            updateAdapter(cachedList, false);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 显示Loading的小动画,并在后台读取课程列表
        showLoading(true);
        mLoadingTask = new AnnouncementLoadingTask();
        mLoadingTask.execute((Void) null);

        return linearLayout;
    }


    @Override
    public void onRefresh() {
        if (mLoadingTask == null) {
            mLoadingTask = new AnnouncementLoadingTask();
            mLoadingTask.execute((Void) null);
        }
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
    private void showLoading(final boolean show) {
        // 逐渐显示mRecyclerView的小动画
        int shortAnimTime = 200;

//        mRecyclerView.setVisibility(show ? View.GONE : View.VISIBLE);
//        mRecyclerView.animate().setDuration(shortAnimTime).alpha(
//                show ? 0 : 1).setListener(new AnimatorListenerAdapter() {
//            @Override
//            public void onAnimationEnd(Animator animation) {
//                mRecyclerView.setVisibility(show ? View.GONE : View.VISIBLE);
//            }
//        });

        mAnnouncementListSwipeContainer.setRefreshing(show);
    }

    private void saveCachedAnnouncementsList(String rootNodeStr) throws Exception {
        FragmentActivity fa = getActivity();
        if (fa == null) {
            throw new Exception("Unknown Error: Null getActivity()!");
        }
        SharedPreferences sharedPreferences = fa.getSharedPreferences("cached_xml", Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putString("announcement_list_str", rootNodeStr);
        editor.apply();
    }

    private String getCachedAnnouncementsList() throws Exception {
        FragmentActivity fa = getActivity();
        if (fa == null) {
            throw new Exception("Unknown Error: Null getActivity()!");
        }
        SharedPreferences sharedPreferences = fa.getSharedPreferences("cached_xml", Context.MODE_PRIVATE);
        return sharedPreferences.getString("announcement_list_str", null);
    }


    private void updateAdapter(String rootNodeStr, boolean showAnimation) {
        // 解析返回的HTML
        ArrayList<AnnouncementInfo> announcement_list = new ArrayList<>();

        FragmentActivity fa = getActivity();
        if (fa == null) {
            return;
        }

        Element list = Jsoup.parse(rootNodeStr).getElementById("announcementList");
        if (list != null) {
            Elements nList = list.children();

            for (int temp = 0; temp < nList.size(); temp++) {
                Element n = nList.get(temp);
                announcement_list.add(new AnnouncementInfo(n));
            }
        }
        adapter.updateList(announcement_list);
        // 显示课程列表的fancy的动画
        if (showAnimation)
            mRecyclerView.scheduleLayoutAnimation();
    }

    /**
     * 为了方便管理课程列表,将每个课程的各种信息组成一个类。
     */
    public static class AnnouncementInfo implements Comparable<AnnouncementInfo> {
        private Element nNode;

        AnnouncementInfo(Element nNode) {
            this.nNode = nNode;
        }

        public String getAuthorInfo() {
            return nNode.getElementsByClass("announcementInfo").first().toString();
        }

        public String getContents() {
            Element tmp = nNode.getElementsByClass("details").first().getElementsByClass("vtbegenerated").first();
            return tmp == null ? "" : tmp.toString();
        }

        public String getAnnouncementTitle() {
            return nNode.child(0).text();
        }

        public String getAnnouncementDate() {
            return nNode.getElementsByClass("details").first().child(0).text().replace("发帖时间: ", "");
        }

        public String getAnnouncementId() {
            return nNode.attr("id");
        }

        //给出可以比较的Date类型
        private Date changeToDate() throws ParseException {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年M月d日", Locale.CHINA);
            return dateFormat.parse(getAnnouncementDate().split(" ")[0]);
        }

        @Override
        public int compareTo(AnnouncementListFragment.AnnouncementInfo comp) {
            try {
//                if (this.changeToDate() == comp.changeToDate())
                return comp.changeToDate().compareTo(this.changeToDate());
            } catch (ParseException e) {
//                e.printStackTrace();//这个是字符串不符合定义的格式的错误
            }
            return this.getAnnouncementTitle().compareTo(comp.getAnnouncementTitle());
        }
    }

    @SuppressLint("StaticFieldLeak")
    private class AnnouncementLoadingTask extends AsyncTask<Void, Void, String> {

        AnnouncementLoadingTask() {
        }

        //主要是有个course id一串数字是不一样的
        @Override
        protected String doInBackground(Void... params) {
            return Utils.courseHttpGetRequest("http://course.pku.edu.cn/webapps/blackboard/execute/announcement?method=search&returnUrl=/webapps/portal/execute/tabs/tabAction?tab_tab_group_id=_3_1&tabId=_1_1");
        }

        @Override
        protected void onPostExecute(final String str) {
            mLoadingTask = null;
            showLoading(false);
            // 出现了错误
            if (str.startsWith(Utils.errorPrefix)) {
                if (str.equals(Utils.errorPrefix + Utils.errorPasswordIncorrect)) {
                    // 密码错误
                    try {
                        Utils.SignOut(getActivity());
                    } catch (Exception e) {
                        if (mRecyclerView.isAttachedToWindow())
                            Snackbar.make(mRecyclerView, e.getMessage(), Snackbar.LENGTH_SHORT).show();
                    }
                } else {
                    // 其他网络错误
                    if (mRecyclerView.isAttachedToWindow())
                        Snackbar.make(mRecyclerView, str, Snackbar.LENGTH_SHORT).show();
                }
            } else {
                updateAdapter(str, true);
                try {
                    saveCachedAnnouncementsList(str);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        // 没什么用的函数
        @Override
        protected void onCancelled() {
            mLoadingTask = null;
            showLoading(false);
        }
    }
}