package jp.sourceforge.nicoro;

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

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.widget.CompoundButton;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.ToggleButton;

import java.util.LinkedList;

import jp.sourceforge.nicoro.AbstractNicoroPlayer.MessageData;

public class NicoroLivePlayer extends Activity
        implements SurfaceVideoDrawer.DrawMessage {
    private static final boolean DEBUG_LOGV = Release.IS_DEBUG && true;
    private static final boolean DEBUG_LOGD = Release.IS_DEBUG && true;

    public static final String INTENT_NAME_LIVE_NUMBER = "LIVE_NUMBER";
    public static final String INTENT_NAME_TITLE = "TITLE";
    public static final String INTENT_NAME_DESCRIPTION = "DESCRIPTION";

    private static final int MSG_ID_GET_PLAYER_STATUS_SUCCEEDED = 0;
    private static final int MSG_ID_GET_PLAYER_STATUS_FAILED = 1;
    private static final int MSG_ID_SURFACE_READY = 2;
    private static final int MSG_ID_SURFACE_DESTROYED = 3;
    private static final int MSG_ID_LIVE_CONNECT_SUCCEEDED = 4;
    private static final int MSG_ID_LIVE_CONNECT_FAILED = 5;
    private static final int MSG_ID_MESSAGE_CONNECTED = 6;
    private static final int MSG_ID_MESSAGE_OCCURRED_ERROR = 7;
    private static final int MSG_ID_INFO_TIME_UPDATE = 8;
    private static final int MSG_ID_PLAY_ERROR = 9;

    private static final long INTERVAL_TIME_UPDATE = 100L;

    private class PrepareFFmpegTask extends AsyncTask<Void, Void, Void> {
        @Override
        protected Void doInBackground(Void... params) {
            // TODO
            try {
//                mFFmpegVideoDecoder.prepareFFmpeg(false);
                mFFmpegVideoDecoder.prepareFFmpeg(true);
            } catch (IllegalArgumentException e) {
                String error = e.toString();
                Log.e(LOG_TAG, error, e);
                Handler handler = mHandler;
                if (handler != null) {
                    handler.obtainMessage(MSG_ID_PLAY_ERROR,
                            error).sendToTarget();
                }
            }
            return null;
        }
    }

    private class AsyncDestroyTask extends AsyncTask<Void, Void, Void> {
        @Override
        protected Void doInBackground(Void... params) {
            mStreamAudioPlayer.finish();
            mStreamAudioPlayer = null;
            mLiveVideoLoader.close();
            mLiveVideoLoader.quit();
//            mLivePlayerStatusLoader.finish();
//            mLivePlayerStatusLoader = null;
            mSurfaceVideoDrawer.quit();
            mSurfaceVideoDrawer = null;
            mFFmpegVideoDecoder.quit();
            mFFmpegVideoDecoder = null;
            if (mLiveMessageLoader != null) {
                mLiveMessageLoader.finish();
                mLiveMessageLoader = null;
            }
            mLiveVideoLoader.free();
            mLiveVideoLoader = null;
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            mAsyncDestroyTask = null;
        }
    }
    private AsyncDestroyTask mAsyncDestroyTask;

    private SurfaceVideoDrawer mSurfaceVideoDrawer;
    /*private*/ StreamAudioPlayer mStreamAudioPlayer = new StreamAudioPlayer();
    private FFmpegVideoDecoder mFFmpegVideoDecoder;
    private LiveMessageLoader mLiveMessageLoader;
    private LiveVideoLoader mLiveVideoLoader;
    private LivePlayerStatusLoader mLivePlayerStatusLoader;
    private MessageChatController mMessageChatController = new MessageChatController();
    private MessageData mMessageData = new MessageData();

    private RelativeLayout mProgressGroup;
    private ProgressBar mProgressBar;
    private VariableLabelView mProgressTextVideo;
    private VariableLabelView mProgressTextThumbinfo;
    private VariableLabelView mProgressTextMessage;
    private VariableLabelView mProgressTextInner;

    private VariableLabelView mInfoCountPlay;
    private VariableLabelView mInfoCountComment;
    private VariableLabelView mInfoTitle;
    private VariableLabelView mInfoDescription;
    private VariableLabelView mInfoPlayData;
    private VariableLabelView mInfoTime;
    private VariableLabelView mInfoSheet;
    private ViewGroup mPlayerInfo;

    private ToggleButton mButtonCommentOnOff;
    private ViewGroup mPlayerController;

    private String mLiveNumber;
    private String mCookieUserSession;
    private String mTitle;
    private String mDescription;
    private long mStartTime;
    private boolean mMessageDisable;

    private long mDeviceStartTime;
    private long mGetPlayerStatusTime;
    private long mLiveStartTime;

    private String mResInfoLivePastTime;

    private SharedPreferences mSharedPreferences;

    private PlayerInfoControllerManager mPlayerInfoControllerManager;

    private final Rational mRationalCurrentPosition = new Rational();
    private boolean mIsRestored;
    private boolean mOnResumed;
    private boolean mFromOnPause;

    private volatile boolean mIsPlaying = false;
    private boolean mIsSurfaceOk;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (mHandler == null) {
                if (DEBUG_LOGD) {
                    Log.d(LOG_TAG, Log.buf().append("Activity was destroyed. ignore message=")
                            .append(msg.toString()).toString());
                }
                return;
            }

            if (DEBUG_LOGV) {
                Log.v(LOG_TAG, Log.buf().append("NicoroLivePlayer handleMessage: ")
                        .append(msg.toString()).toString());
            }
            switch (msg.what) {
                case MSG_ID_GET_PLAYER_STATUS_SUCCEEDED:
                    if (mOnResumed) {
                        mProgressTextThumbinfo.setText(
                                getString(R.string.progress_thumbinfo_finished));
                        mProgressTextThumbinfo.clearAnimation();

                        mDeviceStartTime = System.currentTimeMillis();
                        mGetPlayerStatusTime = mLivePlayerStatusLoader.getTime();
                        mLiveStartTime = mLivePlayerStatusLoader.getStartTime();

                        // TODO コメント数等の定期的な更新
                        // →http://watch.live.nicovideo.jp/api/heartbeat?v=（放送ID）
                        //   http://live.nicovideo.jp/api/heartbeat?v=（放送ID）

                        // TODO getplayerstatusでは文が途中で途切れる。タイトルも長ければ同様
                        String title = mTitle;
                        if (title == null) {
                            title = mLivePlayerStatusLoader.getTitle();
                        }
                        mInfoTitle.setText(title);
                        String description = mDescription;
                        if (description == null) {
                            description = mLivePlayerStatusLoader.getDescription();
                        }
                        mInfoDescription.setText(description);
                        mInfoCountPlay.getTextBuilder()
                            .append(getString(R.string.info_live_count_watch))
                            .append(mLivePlayerStatusLoader.getWatchCount());
                        mInfoCountPlay.notifyUpdateText();
                        mInfoCountComment.getTextBuilder()
                            .append(getString(R.string.info_live_count_comment))
                            .append(mLivePlayerStatusLoader.getCommentCount());
                        mInfoCountComment.notifyUpdateText();
                        mInfoSheet.setText(getString(R.string.info_live_sheet,
                                mLivePlayerStatusLoader.getRoomLabel(),
                                mLivePlayerStatusLoader.getRoomSeetNo()));


                        CallbackMessage<Void, LiveVideoLoader.ErrorCode> callbackLiveVideo =
                            new CallbackMessage<Void, LiveVideoLoader.ErrorCode>(
                                    mHandler, MSG_ID_LIVE_CONNECT_SUCCEEDED, MSG_ID_LIVE_CONNECT_FAILED);
                        String url = mLivePlayerStatusLoader.getRtmpUrl();
                        if (url == null) {
                            url = mLivePlayerStatusLoader.getContentsUrl();
                            if (url == null) {
                                // TODO 状況によってはnullになりえる？（通常動画再生指定など）
                                String errorMessage = getString(
                                        R.string.errormessage_live_unsupported);
                                Util.showErrorDialog(NicoroLivePlayer.this,
                                        errorMessage, true);
                                return;
                            }
                        }
    //                    url += "/" + mLiveNumber;
    //                    // TODO アクセスできないかつ端末ごとフリーズする傾向があるのでエラーで終了
    //                    if (url.indexOf("/fileorigin/") >= 0) {
    //                        Util.showErrorDialog(NicoroLivePlayer.this,
    //                                getString(R.string.errormessage_live_unsupported), true);
    //                        return;
    //                    }

                        String extras = null;
                        String playpath = mLivePlayerStatusLoader.getContentsPlaypath();
                        if (playpath == null) {
    //                        playpath = mLivePlayerStatusLoader.getQuePlaypath();
                            playpath = mLivePlayerStatusLoader.getQueContent();
                            if (playpath == null) {
                                // TODO
                                playpath = mLiveNumber;
                            }
                        } else {
                            String contentsUrl = mLivePlayerStatusLoader.getContentsUrl();
                            if (contentsUrl != null) {
//                                extras = " subscribe=" + contentsUrl + playpath;
//                                playpath = "rtmp:" + contentsUrl + playpath;
//                                extras = " conn=S:" + contentsUrl + " conn=S:" + playpath + " conn=S:" + mLiveNumber;
//                                extras = " tcUrl=" + url;
//                                url = contentsUrl;
//                                playpath = playpath + "&" + contentsUrl + "&" + mLiveNumber;
//                                extras = " subscribe=" + "nlPlayNotice";
                                extras = " nlPlayNotice1=" + contentsUrl + " nlPlayNotice2=" + playpath;
                            }
//                            extras = " subscribe=" + playpath;
//                            playpath = mLiveNumber;
//                            extras = " subscribe=" + mLiveNumber;
//                            playpath = "rtmp:" + playpath;
//                            extras = " swfVfy=1 swfAge=0";
                        }
                        // TODO 必ずタイムシフトかどうか？
                        boolean live = (mLivePlayerStatusLoader.getArchive() == 0);
                        int start;
                        if (live) {
                            start = 0;
                        } else {
                            start = mLivePlayerStatusLoader.getQueVpos() / -100;
                        }
                        String ticket = mLivePlayerStatusLoader.getRtmpTicket();
    //                    String ticket = null;
    //                    String akamaiUser = mLivePlayerStatusLoader.getAkamaiUser();
    //                    String akamaiPassword = mLivePlayerStatusLoader.getAkamaiPassword();
    //                    String queContent = mLivePlayerStatusLoader.getQueContent();
    //                    if (queContent != null) {
    //                        extras = "conn=NS:sendFileRequest:" + queContent;
    //                    }
//                        extras = " token=" + ticket;
                        mLiveVideoLoader.startConnect(url, ticket, playpath, live, start,
                                mLiveNumber,
    //                            akamaiUser, akamaiPassword,
                                extras,
                                callbackLiveVideo);

                        if (mLiveMessageLoader != null) {
                            mLiveMessageLoader.finish();
                        }
                        mLiveMessageLoader = new LiveMessageLoader(
                                mLivePlayerStatusLoader.getMsAddr(),
                                mLivePlayerStatusLoader.getMsPort(),
                                mLivePlayerStatusLoader.getMsThread(),
                                mCookieUserSession,
                                mLivePlayerStatusLoader.getUserId(),
                                getApplicationContext());
                        mLiveMessageLoader.setEventListener(new LiveMessageLoader.EventListener() {
                            @Override
                            public void onConnected(LiveMessageLoader loader) {
                                Handler handler = mHandler;
                                if (handler != null) {
                                    handler.sendEmptyMessage(MSG_ID_MESSAGE_CONNECTED);
                                }
                            }
                            @Override
                            public void onOccurredError(LiveMessageLoader loader, String errorMessage) {
                                Handler handler = mHandler;
                                if (handler != null) {
                                    handler.sendEmptyMessage(MSG_ID_MESSAGE_OCCURRED_ERROR);
                                }
                            }
                            @Override
                            public void onFinished(LiveMessageLoader loader) {
                                // nothing
                            }
                            @Override
                            public void onAddedMessage(LiveMessageLoader loader) {
                                // TODO 自動生成されたメソッド・スタブ

                            }
                        });
                        mLiveMessageLoader.startLoad();
                    } else {
                        // 前面に出ていないときは無視
                        if (DEBUG_LOGD) {
                            Log.d(LOG_TAG, "MSG_ID_GET_PLAYER_STATUS_SUCCEEDED not onResume, ignore");
                        }
                    }
                    break;
                case MSG_ID_GET_PLAYER_STATUS_FAILED: {
                    if (mOnResumed) {
                        mProgressTextThumbinfo.setText(
                                getString(R.string.progress_thumbinfo_error));
                        mProgressTextThumbinfo.clearAnimation();

                        String errorMessage = (String) msg.obj;
                        Util.showErrorDialog(NicoroLivePlayer.this,
                                errorMessage, true);
                    } else {
                        // 前面に出ていないときは無視
                        if (DEBUG_LOGD) {
                            Log.d(LOG_TAG, "MSG_ID_GET_PLAYER_STATUS_SUCCEEDED not onResume, ignore");
                        }
                    }
                } break;
                case MSG_ID_SURFACE_READY:
                    mIsSurfaceOk = true;
                    // TODO
                    if (!mIsPlaying && canStartPlay()) {
                        startPlay();
                    }
                    break;
                case MSG_ID_SURFACE_DESTROYED:
                    mIsSurfaceOk = false;
                    break;
                case MSG_ID_LIVE_CONNECT_SUCCEEDED:

                    // TODO
                    new PrepareFFmpegTask().execute();
//                    mFFmpegVideoDecoder.prepareFFmpeg(true);
//                    mFFmpegVideoDecoder.prepareFFmpeg(false);
                    break;
                case MSG_ID_LIVE_CONNECT_FAILED: {
                    if (!isFinishing()) {
                        LiveVideoLoader.ErrorCode errorCode =
                            (LiveVideoLoader.ErrorCode) msg.obj;
                        int stringId;
                        switch (errorCode) {
                            case FAIL_SETUP_URL:
                                stringId = R.string.errormessage_live_setup;
                                break;
                            case FAIL_CONNECT:
                            case FAIL_CONNECT_STREAM:
                                stringId = R.string.errormessage_live_connect;
                                break;
                            case FAIL_RECONNECT_STREAM:
                                stringId = R.string.errormessage_live_reconnect;
                                break;
                            case FAIL_CACHE_FILE:
                                stringId = R.string.errormessage_live_cache_file;
                                break;
                            case READ_ERROR:
                                stringId = R.string.errormessage_live_read_error;
                                break;
                            case READ_COMPLETE:
                                stringId = R.string.errormessage_live_read_complete;
                                break;
                            default:
                                assert false : errorCode;
                                stringId = R.string.errormessage_unknown;
                                break;
                        }
                        String errorMessage = getString(stringId);
                        Util.showErrorDialog(NicoroLivePlayer.this,
                                errorMessage, true);
                    }
                } break;
                case MSG_ID_MESSAGE_CONNECTED:
                    mProgressTextMessage.setText(
                            getString(R.string.progress_message_live_connected));
                    mProgressTextMessage.clearAnimation();
                    break;
                case MSG_ID_MESSAGE_OCCURRED_ERROR:
                    mProgressTextMessage.setText(
                            getString(R.string.progress_message_live_error));
                    mProgressTextMessage.clearAnimation();
                    break;
                case MSG_ID_INFO_TIME_UPDATE:
                    if (!isFinishing()) {
                        if (mOnResumed) {
                            StringBuilder infoTimeData = mInfoTime.getTextBuilder();
                            infoTimeData.setLength(0);
                            if (mLivePlayerStatusLoader.getArchive() == 0) {
                                // 生放送
                                infoTimeData.append(mResInfoLivePastTime);
                                int timeS = (int) ((System.currentTimeMillis() - mDeviceStartTime) / 1000);
                                if (mGetPlayerStatusTime > 0 && mLiveStartTime > 0) {
                                    timeS += (mGetPlayerStatusTime - mLiveStartTime);
                                }
                                int s = timeS % 60;
                                int m = timeS / 60 % 60;
                                int h = timeS / (60 * 60);
                                Util.appendPlayTime(infoTimeData, h, m, s);
                            } else {
                                // タイムシフト
                                mSurfaceVideoDrawer.getCurrentPosition(mRationalCurrentPosition);
                                final int posNum = mRationalCurrentPosition.num;
                                final int posDen = mRationalCurrentPosition.den;
                                if (posDen != 0) {
                                    int minutes = posNum / (posDen * 60);
                                    int seconds = posNum / posDen % 60;
                                    Util.appendPlayTime(infoTimeData, minutes, seconds);
                                } else {
                                    infoTimeData.append(AbstractNicoroPlayer.INFO_TIME_DEFAULT);
                                }
                            }
                            mInfoTime.notifyUpdateText();

                            // 繰り返し
                            mHandler.sendEmptyMessageDelayed(
                                    MSG_ID_INFO_TIME_UPDATE, INTERVAL_TIME_UPDATE);
                        }
                    }
                    break;
                case MSG_ID_PLAY_ERROR:
                    Util.showErrorDialog(NicoroLivePlayer.this,
                            (String) msg.obj, true);
                    break;
                default:
                    assert false : msg.what;
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        if (DEBUG_LOGV) {
            Log.v(LOG_TAG, Log.buf().append(getClass().getName())
                    .append("#onCreate: savedInstanceState=")
                    .append(savedInstanceState).toString());
        }
        super.onCreate(savedInstanceState);


        if (savedInstanceState == null) {
            mIsRestored = false;
        } else {
            mIsRestored = true;
        }

        mOnResumed = false;
        mFromOnPause = false;

        Intent intent = getIntent();
        String liveNumber = intent.getStringExtra(INTENT_NAME_LIVE_NUMBER);
        mLiveNumber = liveNumber;
        String cookieUserSession = intent.getStringExtra(AbstractNicoroPlayer.INTENT_NAME_COOKIE_USER_SESSION);
        mCookieUserSession = cookieUserSession;
        mTitle = intent.getStringExtra(INTENT_NAME_TITLE);
        mDescription = intent.getStringExtra(INTENT_NAME_DESCRIPTION);
//        mLivePlayerStatusLoader = new LivePlayerStatusLoader(liveNumber,
//                cookieUserSession);
//        CallbackMessage<Void, String> callbackLivePlayerStatus = new CallbackMessage<Void, String>(
//                mHandler, MSG_ID_GET_PLAYER_STATUS_SUCCEEDED, MSG_ID_GET_PLAYER_STATUS_FAILED);
//        mLivePlayerStatusLoader.registerCallback(callbackLivePlayerStatus);
//        mLivePlayerStatusLoader.startLoad();

        setContentView(R.layout.nicoro_liveplayer);
        mSurfaceVideoDrawer = new SurfaceVideoDrawer(
                (SurfaceView) findViewById(R.id.surface));
        mSurfaceVideoDrawer.registerEventHandler(mHandler,
                MSG_ID_SURFACE_READY, MSG_ID_SURFACE_DESTROYED);
        mSurfaceVideoDrawer.setDrawMessage(this);
        mLiveVideoLoader = new LiveVideoLoader();
        mLiveVideoLoader.start();

        mFFmpegVideoDecoder = new FFmpegVideoDecoder(mSurfaceVideoDrawer,
                mStreamAudioPlayer, mLiveVideoLoader, NicoroLivePlayer.this);

        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(
                getApplicationContext());
        mSharedPreferences = sharedPreferences;
        boolean messageAntialias = sharedPreferences.getBoolean(
                getString(R.string.pref_key_message_antialias), false);
        mMessageChatController.setAntiAlias(messageAntialias);

        mMessageDisable = sharedPreferences.getBoolean(
                getString(R.string.pref_key_message_disable), false);

        mMessageData.mChatsWait =
            new LinkedList<MessageChat>();
        mMessageData.mChatsRunningNaka =
            new LinkedList<MessageChat>();
        mMessageData.mChatsRunningShita =
            new LinkedList<MessageChat>();
        mMessageData.mChatsRunningUe =
            new LinkedList<MessageChat>();

        Resources res = getResources();
        mResInfoLivePastTime = res.getString(R.string.info_live_time_past);

        initializeView();

        mIsSurfaceOk = false;
        mIsPlaying = false;

        mStartTime = SystemClock.elapsedRealtime();
    }

    @Override
    protected void onResume() {
        super.onResume();
        mOnResumed = true;
        if (mFromOnPause) {
//            if (canStartPlay()) {
//                // TODO
//                startPlay();
//            }
//            assert mLiveVideoLoader != null;
//            mLiveVideoLoader.startReconnect();
            mFromOnPause = false;
        } else {
//            if (canStartPlay()) {
//                startPlay();
//            }
        }
        assert mLivePlayerStatusLoader == null;
        mLivePlayerStatusLoader = new LivePlayerStatusLoader(mLiveNumber,
                mCookieUserSession);
        CallbackMessage<Void, String> callbackLivePlayerStatus = new CallbackMessage<Void, String>(
                mHandler, MSG_ID_GET_PLAYER_STATUS_SUCCEEDED, MSG_ID_GET_PLAYER_STATUS_FAILED);
        mLivePlayerStatusLoader.registerCallback(callbackLivePlayerStatus);
        mLivePlayerStatusLoader.startLoad();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mOnResumed = false;
        mFromOnPause = true;
        // TODO pauseがどうにもうまくいかないので、とりあえず落とす
        if (true) {
            finish();
            return;
        }

        assert mLivePlayerStatusLoader != null;
        mLivePlayerStatusLoader.finish();
        mLivePlayerStatusLoader = null;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mHandler = null;
        if (mAsyncDestroyTask == null) {
            mAsyncDestroyTask = new AsyncDestroyTask();
            mAsyncDestroyTask.execute();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (DEBUG_LOGV) {
            Log.v(LOG_TAG, Log.buf().append(getClass().getName())
                    .append("#onTouchEvent: event=").append(event)
                    .toString());
        }
        if (mPlayerInfoControllerManager.onTouchEvent(event)) {
            return true;
        }
        return super.onTouchEvent(event);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (DEBUG_LOGV) {
            Log.v(LOG_TAG, Log.buf().append(getClass().getName())
                    .append("#onKeyDown: keyCode=").append(keyCode)
                    .append(" event=").append(event)
                    .toString());
        }
        if (mPlayerInfoControllerManager.onKeyDown(keyCode, event)) {
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (DEBUG_LOGV) {
            Log.v(LOG_TAG, Log.buf().append(getClass().getName())
                    .append("#onKeyUp: keyCode=").append(keyCode)
                    .append(" event=").append(event)
                    .toString());
        }
        return super.onKeyUp(keyCode, event);
    }

    // SurfaceVideoDrawer.DrawMessage

    @Override
    public void drawMessage(Canvas canvas, int vpos) {
        // TODO vposは現在時間基準
        vpos = (int) (SystemClock.elapsedRealtime() - mStartTime) / 10;

        mMessageChatController.drawMessageForLive(
                canvas, mMessageData, null, vpos,
                canvas.getWidth(), canvas.getHeight(),
                mMessageDisable, mLiveMessageLoader);
    }

    private void startPlay() {
        mIsPlaying = true;

        mProgressGroup.setVisibility(View.GONE);
        if (!mPlayerInfoControllerManager.isPlayerInfoShown()) {
            mPlayerInfoControllerManager.showPlayerInfo();
        }

        mHandler.sendEmptyMessage(MSG_ID_INFO_TIME_UPDATE);

        mStreamAudioPlayer.prepareStart();
//        mFFmpegVideoDecoder.prepareFFmpeg();
        mFFmpegVideoDecoder.prepareDecode();
        mFFmpegVideoDecoder.start();
    }

    private void initializeView() {
        mProgressGroup = (RelativeLayout) findViewById(R.id.progress_group);
        mProgressBar = (ProgressBar) findViewById(R.id.progress);
        mProgressTextVideo = (VariableLabelView) findViewById(R.id.progress_text_video);
        mProgressTextVideo.setText(getString(R.string.progress_video_wait_connect));
        mProgressTextVideo.startAnimation(
                AnimationUtils.loadAnimation(getApplicationContext(),
                        R.anim.blink));
        mProgressTextThumbinfo = (VariableLabelView) findViewById(R.id.progress_text_thumbinfo);
        mProgressTextThumbinfo.setText(getString(R.string.progress_thumbinfo_wait));
        mProgressTextThumbinfo.startAnimation(
                AnimationUtils.loadAnimation(getApplicationContext(),
                        R.anim.blink));
        mProgressTextMessage = (VariableLabelView) findViewById(R.id.progress_text_message);
        mProgressTextMessage.setText(getString(R.string.progress_message_wait));
        mProgressTextMessage.startAnimation(
                AnimationUtils.loadAnimation(getApplicationContext(),
                        R.anim.blink));
        findViewById(R.id.progress_text_message_fork).setVisibility(View.GONE);
        mProgressTextInner = (VariableLabelView) findViewById(R.id.progress_text_inner);

        mInfoCountPlay = (VariableLabelView) findViewById(R.id.info_count_play);
        mInfoCountComment = (VariableLabelView) findViewById(R.id.info_count_comment);
        mInfoTime = (VariableLabelView) findViewById(R.id.info_time);
        mInfoTitle = (VariableLabelView) findViewById(R.id.info_title);
        mInfoDescription = (VariableLabelView) findViewById(R.id.info_description);
        mInfoPlayData = (VariableLabelView) findViewById(R.id.info_play_data);
        mInfoSheet = (VariableLabelView) findViewById(R.id.info_sheet);
        mPlayerInfo = (ViewGroup) findViewById(R.id.player_info);

        mButtonCommentOnOff = (ToggleButton) findViewById(R.id.button_comment_onoff);
        mButtonCommentOnOff.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView,
                    boolean isChecked) {
                boolean messageDisable = !isChecked;
                if (mMessageDisable != messageDisable) {
                    mMessageDisable = messageDisable;
                    SharedPreferences.Editor editor = mSharedPreferences.edit();
                    editor.putBoolean(
                            getString(R.string.pref_key_message_disable),
                            mMessageDisable);
                    editor.commit();
                }
            }
        });
        mButtonCommentOnOff.setChecked(!mMessageDisable);
        mPlayerController = (ViewGroup) findViewById(R.id.player_controller);

        // Viewが必要なためここで初期化
        mPlayerInfoControllerManager = new PlayerInfoControllerManager(
                getApplicationContext(), mPlayerInfo, mPlayerController, mInfoTime);
    }

    private boolean canStartPlay() {
        return mOnResumed && mIsSurfaceOk;

    }
}
