package jp.sourceforge.nicoro;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Browser;
import android.support.v4.app.ListFragment;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static jp.sourceforge.nicoro.Log.LOG_TAG;
import jp.gr.java_conf.shiseissi.commonlib.CollUtil;
import jp.gr.java_conf.shiseissi.commonlib.ViewUtil;
import jp.sourceforge.nicoro.StaticRes.string;

public class BookmarksFragment extends ListFragment {

    private static final String KEY_URL = "url";
    private static final String KEY_TITLE = "title";

    private static final String KEY_BOOKMARK_LIST = "BOOKMARK_LIST";

    private Context mContext;

    private ArrayList<HashMap<String, String>> mBookmarkList;

    private String mAddBookmarkUrl = "";
    private String mAddBookmarkTitle = "";

    private View mAddBookmarkHeaderView;
    private TextView mAddBookmarkUrlView;
    private Button mAddBookmarkButtonView;

    private ListEmptyProgressManager mEmptyProgress;

    private StateManager mStateManager = new StateManager();

    private class CreateBookmarkListTask extends AsyncTask<ArrayList<HashMap<String, String>>, Void, ArrayList<HashMap<String, String>>> {
        @Override
        protected ArrayList<HashMap<String, String>> doInBackground(
                ArrayList<HashMap<String, String>>... params) {
            ArrayList<HashMap<String, String>> bookmarkList = params[0];

            ContentResolver cr = mContext.getContentResolver();
            Cursor c = cr.query(Browser.BOOKMARKS_URI,
                    new String[] {
                        Browser.BookmarkColumns.URL,
                        Browser.BookmarkColumns.TITLE
                    },
                    Browser.BookmarkColumns.BOOKMARK + "=1 AND "
                    + Browser.BookmarkColumns.URL + " GLOB ?",
                    new String[] {
                        "*.nicovideo.jp*"
                    },
                    null);
            if (c == null) {
                // rootedでブラウザ削除していると見つからない場合も
                Log.w(LOG_TAG, "BOOKMARKS_URI are not found.");
                if (bookmarkList == null) {
                    bookmarkList = new ArrayList<HashMap<String, String>>();
                }
                return bookmarkList;
            }
            try {
                if (bookmarkList == null) {
                    bookmarkList = new ArrayList<HashMap<String, String>>(c.getCount() + 1);
                } else {
                    bookmarkList.clear();
                }

                if (c.moveToFirst()) {
                    final int indexUrl = c.getColumnIndex(
                            Browser.BookmarkColumns.URL);
                    final int indexTitle = c.getColumnIndex(
                            Browser.BookmarkColumns.TITLE);
                    do {
                        final String url = c.getString(indexUrl);
                        // XXX urlが空の場合がある？
                        if (url != null) {
                            final String title = c.getString(indexTitle);

                            HashMap<String, String> bookmark = CollUtil.newHashMap(2);
                            bookmark.put(KEY_URL, url);
                            bookmark.put(KEY_TITLE, title);
                            bookmarkList.add(bookmark);
                        }
                    } while (c.moveToNext());
                }
            } finally {
                c.close();
            }
            return bookmarkList;
        }

        @Override
        protected void onPostExecute(ArrayList<HashMap<String, String>> result) {
            assert result != null;
            if (mCreateBookmarkListTask == this) {
                // 後から別のTaskが起動していない→表示に反映
                mBookmarkList = result;
                if (!mStateManager.wasDestroyed()) {
                    setListAdapter(createAdapter(mBookmarkList));
                }

                mEmptyProgress.showEmptyText();
                mCreateBookmarkListTask = null;
            }
        }
    }
    private CreateBookmarkListTask mCreateBookmarkListTask;

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

        mStateManager.onCreate(savedInstanceState);

        mContext = getActivity().getApplicationContext();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.bookmarks_list, container, false);
        mEmptyProgress = new ListEmptyProgressManager(v);
        return v;
    }

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

        ListView listView = getListView();
        if (savedInstanceState != null) {
            byte[] gzipBytes = savedInstanceState.getByteArray(KEY_BOOKMARK_LIST);
            ArrayList<HashMap<String, String>> bookmarkList =
                Util.inflateSerializable(gzipBytes);
            if (bookmarkList != null) {
                listView.setAdapter(createAdapter(bookmarkList));
            }
        }
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
                Activity a = getActivity();
                if (a instanceof WebBrowserFragmentStarter) {
                    WebBrowserFragmentStarter starter =
                        (WebBrowserFragmentStarter) a;
                    ListView listView = (ListView) parent;
                    ListAdapter adapter = listView.getAdapter();
                    @SuppressWarnings("unchecked")
                    HashMap<String, Object> bookmark =
                        (HashMap<String, Object>) adapter.getItem(position);

                    starter.startWebBrowserFragment((String) bookmark.get(KEY_URL));
                }
            }
        });
    }

    @Override
    public void onStart() {
        super.onStart();
        mStateManager.onStart();
    }

    @SuppressWarnings("unchecked")
    @Override
    public void onResume() {
        super.onResume();
        mStateManager.onResume();

        // 前回のTaskがまだ動作中かもしれないがメンバ上書きして実行
//        setListAdapter(null);
        mCreateBookmarkListTask = new CreateBookmarkListTask();
        mCreateBookmarkListTask.execute(mBookmarkList);

        mEmptyProgress.showEmptyProgress();

        // ブックマーク表示のタイミングでもブラウザから情報取得
        updateAddBookmarkByBrowser();

        // HeaderViewではリストが空の時に表示されなくなってしまう
        if (mAddBookmarkHeaderView == null) {
//            LayoutInflater inflater = getActivity().getLayoutInflater();
//            mAddBookmarkHeaderView = inflater.inflate(R.layout.bookmarks_add, null, true);
//            getListView().addHeaderView(mAddBookmarkHeaderView);
            mAddBookmarkHeaderView = ViewUtil.findViewById(getActivity(), R.id.bookmarks_add);
        }
        // Activityずれるとnullになることがある？ので再チェック
        if (mAddBookmarkHeaderView != null) {
            mAddBookmarkButtonView = ViewUtil.findViewById(mAddBookmarkHeaderView,
                    android.R.id.text1);
            mAddBookmarkUrlView = ViewUtil.findViewById(mAddBookmarkHeaderView,
                    android.R.id.text2);
            mAddBookmarkButtonView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (!TextUtils.isEmpty(mAddBookmarkUrl)) {
                        BookmarksFragment.addBookmark(getActivity(),
                                mAddBookmarkTitle, mAddBookmarkUrl);
                    }
                }
            });
        }
        if (mAddBookmarkUrlView != null) {
            mAddBookmarkUrlView.setText(mAddBookmarkUrl);
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        mStateManager.onPause();
    }

    @Override
    public void onStop() {
        super.onStop();
        mStateManager.onStop();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mStateManager.onSaveInstanceState();
        // サイズが大きい懸念があるので圧縮
        byte[] gzipBytes = Util.deflateSerializable(mBookmarkList);
        outState.putByteArray(KEY_BOOKMARK_LIST, gzipBytes);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mStateManager.onDestroy();
    }

    public void updateAddBookmarkByBrowser() {
        WebBrowserFragment webBrowser = ViewUtil.findFragmentByTag(
                getFragmentManager(), string.tag_webbrowser_fragment);
        if (webBrowser == null) {
            // Intentにあればパラメータ取得
            Activity activity = getActivity();
            if (activity != null) {
                Intent intent = activity.getIntent();
                ListMenuView.updateFragmentBookmarks(intent, this);
            }
        } else {
            String title = webBrowser.getWebTitle();
            String url = webBrowser.getWebUrl();
            if (!TextUtils.isEmpty(title) && !TextUtils.isEmpty(url)) {
                setAddBookmark(url, title);
            }
        }
    }

    @Override
    public void onHiddenChanged(boolean hidden) {
        if (!hidden) {
            // ブックマーク表示のタイミングでもブラウザから情報取得
            updateAddBookmarkByBrowser();
        }
    }

    ListAdapter createAdapter(ArrayList<HashMap<String, String>> bookmarkList) {
        SimpleAdapter adapter = new SimpleAdapter(
                mContext,
                bookmarkList,
                R.layout.bookmarks,
                new String []{KEY_TITLE, KEY_URL},
                new int []{android.R.id.text1, android.R.id.text2}
                );
        return adapter;
    }

    public void setAddBookmark(String url, String title) {
        mAddBookmarkUrl = url;
        mAddBookmarkTitle = title;

        if (mAddBookmarkUrlView != null) {
            mAddBookmarkUrlView.setText(mAddBookmarkUrl);
        }
    }

    public static void addBookmark(Activity activity, String title, String url) {
        Matcher matcher = Pattern.compile(NicoroAPIManager.PATTERN_NICOVIDEO_URL).matcher(url);
        if (matcher.find()) {
            Browser.saveBookmark(activity, title, url);
        } else {
            Util.showErrorToast(activity.getApplicationContext(),
                    R.string.toast_bookmark_url_not_nicovideo);
        }
    }
}
