package jp.sourceforge.nicoro;

import static jp.sourceforge.nicoro.Log.LOG_TAG;

import org.apache.http.protocol.HTTP;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.ListFragment;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;

//import java.io.BufferedInputStream;
//import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.StreamCorruptedException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.concurrent.locks.ReentrantLock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import jp.gr.java_conf.shiseissi.commonlib.ViewUtil;

public class VideoTagFragment extends ListFragment
implements Handler.Callback {
    private static final boolean DEBUG_LOGD = Release.IS_DEBUG & true;

    private static final int MSG_ID_LOAD_FINISHED = 0;
    private static final int MSG_ID_LOAD_OCCURED_ERROR = 1;
    private static final int MSG_ID_CHANGE_LIST = 2;
    private static final int MSG_ID_CHECK_FOOTER_PROGRESS = 3;

    private static final String FILE_VIDEO_TAG_HISTORY = "VideoTagHistory.dat";
    private static final String KEY_VIDEO_TAG_LIST_ADAPTER = "VideoTagListAdapter";

    private static final int VIDEO_TAG_HISTORY_MAX_SIZE = 30;

    private static final int MAX_PAGE = 16;

    Context mContext;
    private SharedPreferences mSharedPreferences;
    private LayoutInflater mLayoutInflater;
    InputMethodManager mInputMethod;

    RssLoader mRssLoader;
    private VideoTagListAdapter mAdapter;

    private VariableLabelView mViewTitle;
    private ListEmptyProgressManager mEmptyProgress;
    AutoCompleteTextView mEditVideoTag;
    Button mButtonSearch;
    private Spinner mSpinnerSort;
    private View mProgressFooter;
    private View mProgressFooterProgress;
    private TextView mProgressFooterText;

    private ViewTreeObserver.OnGlobalLayoutListener mOnGlobalLayoutListener;

    ArrayAdapter<String> mAdapterVideoTagHistory;

    private String mLastUrl;
    LinkedList<String> mListVideoTagHistory;
    static final ReentrantLock mLockWriteVideoTagHistoryFile = new ReentrantLock(true);

    private int mCurrentPage = 1;

    private StateManager mStateManager = new StateManager();

    private final Pattern mPatternEdgeSpace = Pattern.compile("^ *(.*?) *$");
    private final Pattern mPatternPluralSpace = Pattern.compile(" +");

    private String mResStringUpload;
    private String[] mResStringArrayVideoTagSortUrl;

    final HandlerWrapper mHandler = new HandlerWrapper(this);

    @Override
    public boolean handleMessage(Message msg) {
        if (isRemoving()) {
            if (DEBUG_LOGD) {
                Log.d(LOG_TAG, Log.buf().append("Fragment is removing. ignore message=")
                        .append(msg.toString()).toString());
            }
            return true;
        }
        if (mStateManager.wasDestroyed()) {
            if (DEBUG_LOGD) {
                Log.d(LOG_TAG, Log.buf().append("Fragment was destroyed. ignore message=")
                        .append(msg.toString()).toString());
            }
            return true;
        }
        RssLoader result;
        switch (msg.what) {
            case MSG_ID_LOAD_FINISHED:
                result = (RssLoader) msg.obj;
                // 現在実行中のloaderからの通知のみ画面に反映
                if (result == mRssLoader) {
                    mEmptyProgress.showEmptyText();
                    mViewTitle.setText(mRssLoader.getTitle());
//                        mAdapter.setItems(mRssLoader.getItems());
                    mAdapter.addItems(mRssLoader.getItems());
                    mAdapter.notifyDataSetChanged();
                    mRssLoader = null;
                    mHandler.sendEmptyMessage(MSG_ID_CHECK_FOOTER_PROGRESS);
                }
                break;
            case MSG_ID_LOAD_OCCURED_ERROR:
                result = (RssLoader) msg.obj;
                // 現在実行中のloaderからのエラー通知のみ画面に反映
                if (result == mRssLoader) {
                    mEmptyProgress.showEmptyText();
                    if (!mStateManager.wasSavedInstanceState()) {
                        String errorMessage = result.getLastErrorMessage();
                        CloseDialogFragment.createErrorDialog(errorMessage,
                                false).show(getFragmentManager(),
                                        getString(R.string.tag_close_dialog_fragment));
                    }
                    mRssLoader = null;
                }
                break;
            case MSG_ID_CHANGE_LIST:
                // 重複イベントは削除
                mHandler.removeMessages(MSG_ID_CHANGE_LIST);

                mCurrentPage = 1;
                mProgressFooterProgress.setVisibility(View.VISIBLE);
                mProgressFooterText.setVisibility(View.INVISIBLE);
                if (createAndStartRssLoader()) {
                    mEmptyProgress.showEmptyProgress();
                    mViewTitle.setText("");
                    mAdapter.setItems(null);
                    mAdapter.notifyDataSetChanged();
                }
                break;
            case MSG_ID_CHECK_FOOTER_PROGRESS:
                checkShowProgressFooter();
                break;
            default:
                assert false : msg.what;
                break;
        }
        return true;
    }

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

        mStateManager.onCreate(savedInstanceState);

        Context context = getActivity().getApplicationContext();
        mContext = context;
        mSharedPreferences = Util.getDefaultSharedPreferencesMultiProcess(context);
        mInputMethod = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);

        new AsyncTask<Void, Void, LinkedList<String>>() {
            @Override
            protected LinkedList<String> doInBackground(Void... params) {
                mLockWriteVideoTagHistoryFile.lock();
                try {
                    return readVideoTagHistory();
                } finally {
                    mLockWriteVideoTagHistoryFile.unlock();
                }
            }

            @Override
            protected void onPostExecute(LinkedList<String> result) {
                mListVideoTagHistory = result;
                Activity activity = getActivity();
                if (activity != null) {
                    mAdapterVideoTagHistory = new ArrayAdapter<String>(activity,
                            R.layout.video_tag_autocomplete_item, result);
                    if (mEditVideoTag != null) {
                        mEditVideoTag.setAdapter(mAdapterVideoTagHistory);
                    }
                }
            }
        }.execute();

        Resources res = context.getResources();
        mResStringUpload = res.getString(R.string.upload);
        mResStringArrayVideoTagSortUrl = res.getStringArray(R.array.video_tag_sort_url);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        mLayoutInflater = inflater;
        View v = inflater.inflate(R.layout.video_tag_list, container, false);
        mEmptyProgress = new ListEmptyProgressManager(v);
        mViewTitle = ViewUtil.findViewById(v, R.id.list_title);
        mEmptyProgress.showEmptyText();

        mButtonSearch = ViewUtil.findViewById(v, R.id.button_search);
        mButtonSearch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mListVideoTagHistory != null) {
                    assert mAdapterVideoTagHistory != null;
                    String videoTag = getVideoTag();
                    if (videoTag == null) {
                        return;
                    }
                    mListVideoTagHistory.remove(videoTag);
                    mListVideoTagHistory.addFirst(videoTag);
                    if (mListVideoTagHistory.size() > VIDEO_TAG_HISTORY_MAX_SIZE) {
                        mListVideoTagHistory.removeLast();
                    }
                    // 仕方がないのでadapter作り直して再設定
                    Activity activity = getActivity();
                    mAdapterVideoTagHistory = new ArrayAdapter<String>(activity,
                            R.layout.video_tag_autocomplete_item, mListVideoTagHistory);
                    mEditVideoTag.setAdapter(mAdapterVideoTagHistory);
                }
                mInputMethod.hideSoftInputFromWindow(mEditVideoTag.getWindowToken(), 0);
                mHandler.sendEmptyMessage(MSG_ID_CHANGE_LIST);
            }
        });

        mEditVideoTag = ViewUtil.findViewById(v, R.id.edit_video_tag);
        mEditVideoTag.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                switch (actionId) {
                    case EditorInfo.IME_ACTION_SEARCH:
                        mButtonSearch.performClick();
                        return true;
                }
                return false;
            }
        });
        if (mAdapterVideoTagHistory != null) {
            mEditVideoTag.setAdapter(mAdapterVideoTagHistory);
        }

        mSpinnerSort = ViewUtil.findViewById(v, R.id.spinner_sort);
        Activity activity = getActivity();
        ArrayAdapter<?> adapter = ArrayAdapter.createFromResource(activity,
                R.array.video_tag_sort, R.layout.video_tag_spinner_item);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        mSpinnerSort.setAdapter(adapter);

        ListView listView = ViewUtil.findViewById(v, android.R.id.list);
        mProgressFooter = inflater.inflate(R.layout.listview_progress_footer,
                listView, false);
        mProgressFooterProgress = ViewUtil.findViewById(mProgressFooter, R.id.progress_footer_progress);
        mProgressFooterText = ViewUtil.findViewById(mProgressFooter, R.id.progress_footer_text);
        mProgressFooterText.setText(R.string.progress_footer_video_tag_empty);
        listView.addFooterView(mProgressFooter, null, false);

        return v;
    }

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

        ListView listView = getListView();
        mAdapter = new VideoTagListAdapter();
        if (savedInstanceState != null) {
            mAdapter.onRestoreInstanceState(savedInstanceState);
        }
        setListAdapter(mAdapter);
        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;
                    RssLoader.Item item = (RssLoader.Item) mAdapter.getItem(position);
                    if (item == null) {
                        Log.e(LOG_TAG, "VideoTagFragment onItemClick: item is null");
                    } else {
                        String url = item.link;
                        starter.startWebBrowserFragment(url);
                    }
                }
            }
        });
        listView.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
            }
            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
                    int totalItemCount) {
                if (firstVisibleItem + visibleItemCount == totalItemCount) {
                    onShowProgressFooter();
                }
            }
        });
        mOnGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                checkShowProgressFooter();
            }
        };
        listView.getViewTreeObserver().addOnGlobalLayoutListener(mOnGlobalLayoutListener);
    }

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

    @Override
    public void onResume() {
        super.onResume();
        mStateManager.onResume();
        if (mAdapter.getCount() > 0) {
            // リストが既にあるときはキーボードを出さない
            getListView().requestFocus();
            InputMethodManager inputMethod = (InputMethodManager) mContext.getSystemService(
                    Context.INPUT_METHOD_SERVICE);
            if (inputMethod != null) {
                inputMethod.hideSoftInputFromWindow(mEditVideoTag.getWindowToken(),
                        0);
            }
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        mStateManager.onPause();
        mLastUrl = null;

        new AsyncTask<Void, Void, Void>() {
            private LinkedList<String> tempList;

            @Override
            protected void onPreExecute() {
                if (mListVideoTagHistory != null) {
                    tempList = new LinkedList<String>(mListVideoTagHistory);
                }
            }

            @Override
            protected Void doInBackground(Void... params) {
                if (tempList == null) {
                    return null;
                }
                mLockWriteVideoTagHistoryFile.lock();
                try {
                    writeVideoTagHistory(tempList);
                } finally {
                    mLockWriteVideoTagHistoryFile.unlock();
                }
                return null;
            }
        }.execute();
    }

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

    @Override
    public void onDestroyView() {
        ListView listView = getListView();
        listView.getViewTreeObserver().removeGlobalOnLayoutListener(mOnGlobalLayoutListener);
        super.onDestroyView();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mStateManager.onSaveInstanceState();
        mAdapter.onSaveInstanceState(outState);
    }

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

    private boolean createAndStartRssLoader() {
        assert mHandler != null;

        String videoTag = getVideoTag();
        if (videoTag == null) {
            return false;
        }
        try {
            String url = createUrl(videoTag, mCurrentPage);
            if (DEBUG_LOGD) {
                Log.d(LOG_TAG, Log.buf().append("VideoTagSearch: url=").append(url).toString());
            }

            if (TextUtils.equals(mLastUrl, url)) {
                // 前回と同じ場合は読み込み省略
                return false;
            }
            mLastUrl = url;

            // TODO ここでCookie取得すべきかどうか
            String userSession = NicoroConfig.getCookieUserSession(mSharedPreferences);
            RssLoader loader = new RssLoader(
                    url,
                    userSession);
            // TODO: ANR対策の為に***Loader類のabort対応が必要
            if (mRssLoader != null) {
                mRssLoader.finish();
            }
            mRssLoader = loader;
            CallbackMessage<RssLoader, RssLoader> callback = new CallbackMessage<RssLoader, RssLoader>(
                    mHandler, MSG_ID_LOAD_FINISHED, MSG_ID_LOAD_OCCURED_ERROR);
            loader.registerCallback(callback);
            loader.startLoad();
            return true;
        } catch (UnsupportedEncodingException e) {
            Log.e(LOG_TAG, e.toString(), e);
            assert false;
            return false;
        }
    }

    @SuppressWarnings("unchecked")
    private LinkedList<String> readVideoTagHistory() {
        LinkedList<String> list = null;
        FileInputStream inFile = null;
        ObjectInputStream inObject = null;
        try {
            inFile = mContext.openFileInput(FILE_VIDEO_TAG_HISTORY);
//            inObject = new ObjectInputStream(new BufferedInputStream(inFile, 2048));
            inObject = new ObjectInputStream(inFile);
            list = (LinkedList<String>) inObject.readObject();
        } catch (FileNotFoundException e) {
            // 初回動作なら見つからないのは正常
            Log.i(LOG_TAG, e.toString());
        } catch (StreamCorruptedException e) {
            Log.e(LOG_TAG, e.toString(), e);
        } catch (IOException e) {
            Log.e(LOG_TAG, e.toString(), e);
        } catch (ClassNotFoundException e) {
            Log.e(LOG_TAG, e.toString(), e);
        } finally {
            if (inFile != null) {
                try {
                    inFile.close();
                } catch (IOException e) {
                    Log.e(LOG_TAG, e.toString(), e);
                }
            }
            if (inObject != null) {
                try {
                    inObject.close();
                } catch (IOException e) {
                    Log.e(LOG_TAG, e.toString(), e);
                }
            }
        }
        if (list == null) {
            list = new LinkedList<String>();
        }
        return list;
    }

    void writeVideoTagHistory(LinkedList<String> list) {
        FileOutputStream outFile = null;
        ObjectOutputStream outObject = null;
        try {
            outFile = mContext.openFileOutput(FILE_VIDEO_TAG_HISTORY, 0);
//            outObject = new ObjectOutputStream(new BufferedOutputStream(outFile, 2048));
            outObject = new ObjectOutputStream(outFile);
            outObject.writeObject(list);
            outFile.getFD().sync();
        } catch (FileNotFoundException e) {
            Log.e(LOG_TAG, e.toString(), e);
        } catch (IOException e) {
            Log.e(LOG_TAG, e.toString(), e);
        } catch (NullPointerException e) {
            // XXX openFileOutputでまれにNullPointerExceptionが発生することがある模様
            Log.e(LOG_TAG, e.toString(), e);
        } finally {
            if (outFile != null) {
                try {
                    outFile.close();
                } catch (IOException e) {
                    Log.e(LOG_TAG, e.toString(), e);
                }
            }
            if (outObject != null) {
                try {
                    outObject.close();
                } catch (IOException e) {
                    Log.e(LOG_TAG, e.toString(), e);
                }
            }
        }
    }

    String getVideoTag() {
        String videoTag = mEditVideoTag.getText().toString();
        String fixVideoTag = videoTag;
        // 文頭と文末の半角スペース除去
        Matcher matcher = mPatternEdgeSpace.matcher(fixVideoTag);
        if (matcher.find()) {
            fixVideoTag = matcher.group(1);
        } else {
            assert false;
        }
        if (fixVideoTag.length() == 0) {
            mEditVideoTag.setError(getString(R.string.error_video_tag_empty));
            return null;
        } else {
            mEditVideoTag.setError(null);
            matcher = mPatternPluralSpace.matcher(fixVideoTag);
            if (matcher.find()) {
                fixVideoTag = matcher.replaceAll(" ");
            }
            // 予測候補が出てしまうので再設定はやめる
//            if (!fixVideoTag.equals(videoTag)) {
//                mEditVideoTag.setText(fixVideoTag);
//            }
            return fixVideoTag;
        }
    }

    private String createUrl(String videoTag, int page)
    throws UnsupportedEncodingException {
        StringBuilder builder = new StringBuilder("http://www.nicovideo.jp/tag/")
            .append(URLEncoder.encode(videoTag, HTTP.UTF_8)).append('?');
        int sortPos = mSpinnerSort.getSelectedItemPosition();
        String sort = mResStringArrayVideoTagSortUrl[sortPos];
        if (sort.length() > 0) {
            builder.append(sort).append('&');
        }
        if (page > 0) {
            builder.append("page=").append(page).append('&');
        }
        return builder.append("rss=2.0").toString();
    }

    void onShowProgressFooter() {
        if (mHandler.hasMessages(MSG_ID_CHANGE_LIST)) {
            // 読み込みイベントが待機中なら無視
        } else if (mRssLoader == null) {
            if (mCurrentPage >= MAX_PAGE) {
                // removeFooterViewでfooter viewが空になるとクラッシュするときがある
                mProgressFooterProgress.setVisibility(View.INVISIBLE);
                mProgressFooterText.setVisibility(View.VISIBLE);
            } else {
                ++mCurrentPage;
                createAndStartRssLoader();
            }
        }
    }

    void checkShowProgressFooter() {
        ListView listView = getListView();
        if (mAdapter.getCount() > 0 &&
                listView.getLastVisiblePosition() + 1 >= listView.getCount()) {
            onShowProgressFooter();
        }
    }

    private class VideoTagListAdapter extends BaseAdapter {
        private ArrayList<RssLoader.Item> mItems;
        private ThumbnailCacher mThumbnailCacher =
            NicoroApplication.getInstance(getActivity())
                .getThumbnailCacher();

        @Override
        public int getCount() {
            if (mItems == null) {
                return 0;
            } else {
                return mItems.size();
            }
        }

        @Override
        public Object getItem(int position) {
            if (mItems == null) {
                return null;
            } else {
                return mItems.get(position);
            }
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view;
            ListItem listItem;
            if (convertView == null) {
                LayoutInflater inflater = mLayoutInflater;
                view = inflater.inflate(R.layout.ranking, parent, false);
                listItem = new ListItem();
                view.setTag(listItem);
                listItem.thumbnail = ViewUtil.findViewById(view, R.id.thumbnail);
                listItem.title = ViewUtil.findViewById(view, R.id.title);
                listItem.description = ViewUtil.findViewById(view, R.id.description);
                listItem.info1 = ViewUtil.findViewById(view, R.id.info1);
                listItem.info2 = ViewUtil.findViewById(view, R.id.info2);
                listItem.info3 = ViewUtil.findViewById(view, R.id.info3);
                listItem.info4 = ViewUtil.findViewById(view, R.id.info4);
                listItem.info5 = ViewUtil.findViewById(view, R.id.info5);
                listItem.info6 = ViewUtil.findViewById(view, R.id.info6);

                listItem.info2.setVisibility(View.GONE);
                listItem.info3.setVisibility(View.GONE);
                listItem.info4.setVisibility(View.GONE);
                listItem.info5.setVisibility(View.GONE);
                listItem.info6.setVisibility(View.GONE);
            } else {
                view = convertView;
                listItem = (ListItem) convertView.getTag();
            }
            RssLoader.Item item = mItems.get(position);

            AsyncBitmapDrawable drawable;
            ViewGroup.LayoutParams params = listItem.thumbnail.getLayoutParams();
            if (item.thumbnail == null) {
                drawable = new AsyncBitmapDrawable(null,
                        params.width, params.height);
            } else {
                Bitmap bitmap = mThumbnailCacher.getThumbnail(item.thumbnail);
                if (bitmap == null) {
                    drawable = new AsyncBitmapDrawable(params.width, params.height, true);
                    mThumbnailCacher.loadThumbnail(item.thumbnail,
                            new CallbackMessage<Bitmap, Void>(
                                    drawable.getHandler(), 0));
                } else {
                    drawable = new AsyncBitmapDrawable(bitmap,
                            params.width, params.height, true);
                }
            }
            listItem.thumbnail.setImageDrawable(drawable);

            listItem.title.setText(Util.convertHtmlEscapedCharacter(item.title));
            listItem.description.setText(Util.convertHtmlEscapedCharacter(item.description));

            StringBuilder builder = listItem.info1.getTextBuilderWithClear();
            builder.append(item.infoLength)
                .append("｜")
                .append(item.infoDate)
                .append(' ')
                .append(mResStringUpload);
            listItem.info1.notifyUpdateText();

            return view;
        }

        public void setItems(ArrayList<RssLoader.Item> items) {
            if (items == null) {
                if (mItems != null) {
                    mItems.clear();
                }
            } else {
                if (mItems == null) {
                    mItems = new ArrayList<RssLoader.Item>(items);
                } else {
                    mItems.clear();
                    mItems.addAll(items);
                }
            }
        }

        public void addItems(ArrayList<RssLoader.Item> items) {
            if (mItems == null) {
                mItems = new ArrayList<RssLoader.Item>(items);
            } else {
                mItems.addAll(items);
            }
        }

        public void onSaveInstanceState(Bundle outState) {
            // FIXME ViewPagerのFragment復帰でどうしてもクラッシュすることがあるので、いったん実装を変える
//            outState.putParcelableArrayList(KEY_VIDEO_TAG_LIST_ADAPTER, mItems);
            // サイズが大きい懸念があるので圧縮
            byte[] gzipBytes = Util.deflateSerializable(mItems);
            outState.putByteArray(KEY_VIDEO_TAG_LIST_ADAPTER, gzipBytes);
        }

        public void onRestoreInstanceState(Bundle savedInstanceState) {
//            ArrayList<RssLoader.Item> items =
//                savedInstanceState.getParcelableArrayList(KEY_VIDEO_TAG_LIST_ADAPTER);
            byte[] gzipBytes = savedInstanceState.getByteArray(
                    KEY_VIDEO_TAG_LIST_ADAPTER);
            ArrayList<RssLoader.Item> items = Util.inflateSerializable(gzipBytes);
            setItems(items);
        }
    }

    private static class ListItem {
        public ImageView thumbnail;
        public VariableLabelView title;
        public VariableLabelView description;
        public VariableLabelView info1;
        public VariableLabelView info2;
        public VariableLabelView info3;
        public VariableLabelView info4;
        public VariableLabelView info5;
        public VariableLabelView info6;
    }
}
