package jp.sourceforge.nicoro;

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

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.Toast;

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

public class MediaPlayerFragment extends AbstractPlayerFragment
implements MessageView.Callback {
    private static final boolean DEBUG_LOGD = Release.IS_DEBUG & true;

    /** コメントを描画 */
    private static final int MSG_ID_MESSAGE_DRAW_MESSAGE = MSG_ID_SUB_OFFSET + 1;
//  private static final int MSG_ID_WAIT_VIDEO_SIZE_GET = MSG_ID_SUB_OFFSET + 2;
    /** 動画ファイル用ローカルプロキシサーバーの準備完了 */
    private static final int MSG_ID_VIDEO_PROXY_PREPARED = MSG_ID_SUB_OFFSET + 4;
    /** 動画ファイル用ローカルプロキシサーバーへの再接続発生 */
    private static final int MSG_ID_VIDEO_PROXY_RECONNECT = MSG_ID_SUB_OFFSET + 6;
    /** {@link MediaPlayer#MEDIA_INFO_VIDEO_TRACK_LAGGING}が発生 */
    private static final int MSG_ID_VIDEO_TRACK_LAGGING = MSG_ID_SUB_OFFSET + 7;
    /** {@link MediaPlayer#MEDIA_INFO_BAD_INTERLEAVING}が発生 */
    private static final int MSG_ID_BAD_INTERLEAVING = MSG_ID_SUB_OFFSET + 8;
    /** （ワンテンポ遅らせて）setVideoViewLayoutを実行 */
    private static final int MSG_ID_SET_VIDEO_VIEW_LAYOUT = MSG_ID_SUB_OFFSET + 9;

    private boolean mIsVideoProxyOk;
    private boolean mIsVideoViewSizeOk;
    private VideoProxyHttpServer mVideoProxyServer;
//  private VideoProxyRtspServer mVideoProxyServer;
    private boolean mMediaPlayerStreaming;
    private boolean mMediaPlayerShiftStreamToFile;
    private boolean mFullscreen16_9;
    private boolean mHadError;
//  private int mVideoViewWidth = -1;
//    private int mVideoViewHeight = -1;
    private boolean mShownVideoTrackLagging;
    private boolean mShownBadInterleaving;
    private ComputeVideoDisplaySize mComputeVideoDisplaySize =
        new ComputeVideoDisplaySize();
    private int mLastDisplayWidth = -1;
    private int mLastDisplayHeight = -1;
    private int mLastVideoWidth = -1;
    private int mLastVideoHeight = -1;

//  private VideoView mVideoView;
    private MediaSurfaceView mVideoView;
    private MessageView mMessageView;
//  private MediaPlayer mMediaPlayer;
    private ViewGroup mVideoFrame;

    @Override
    public boolean handleMessage(Message msg) {
        switch (msg.what) {
        case MSG_ID_VIDEO_DOWNLOAD_FINISHED:
            super.handleMessage(msg);
            assert mVideoLoader.isCacheCompleted();
            if (canStartPlay()) {
                if (!mDidStartPlay) {
                    startPlay();
                } else if (mMediaPlayerShiftStreamToFile
                        && mMediaPlayerStreaming
                        && mVideoProxyServer != null) {
                    shiftPlayStreamToFile();
                }
            }
            break;
        case MSG_ID_MESSAGE_DRAW_MESSAGE:
            if (!mStateManager.wasDestroyed()) {
                mMessageView.invalidate();

                Message message = mHandler.obtainMessage(
                        MSG_ID_MESSAGE_DRAW_MESSAGE);
                mHandler.sendMessageDelayed(message, 33L);
            }
            break;
//        case MSG_ID_WAIT_VIDEO_SIZE_GET:
//            MediaPlayer mediaPlayer = mMediaPlayer;
//            if (mediaPlayer != null && !mHadError) {
//                // まだIllegalStateException出る場合がある
//                try {
//                    if (mediaPlayer.getVideoWidth() != 0
//                            || mediaPlayer.getVideoHeight() != 0) {
//                        mHandler.sendEmptyMessage(
//                                MSG_ID_INFO_PLAY_DATA_UPDATE);
//                    } else {
//                        mHandler.sendEmptyMessageDelayed(
//                                MSG_ID_WAIT_VIDEO_SIZE_GET, 1000L);
//                    }
//                } catch (IllegalStateException e) {
//                    Log.e(LOG_TAG, e.toString(), e);
//                }
//            }
//            break;
        case MSG_ID_VIDEO_DOWNLOAD_STARTED:
            if (mMediaPlayerStreaming) {
                if (!mVideoLoader.isCacheCompleted()) {
                    // プロキシ開始
//                    mVideoProxyServer = new VideoProxyRtspServer(mVideoLoader);
                    mVideoProxyServer = new VideoProxyHttpServer(mVideoLoader);
                    mVideoProxyServer.registerOnPreparedServer(mHandler,
                            MSG_ID_VIDEO_PROXY_PREPARED);
                    mVideoProxyServer.registerOnReconnectServer(mHandler,
                            MSG_ID_VIDEO_PROXY_RECONNECT);
                    mVideoProxyServer.startProxy();
                }
            }
            break;
        case MSG_ID_VIDEO_PROXY_PREPARED:
            if (mMediaPlayerStreaming) {
                mIsVideoProxyOk = true;
                if (canStartPlay() && !mDidStartPlay) {
                    startPlay();
                }
            }
            break;
        case MSG_ID_VIDEO_CACHED:
            if (mMediaPlayerStreaming) {
                mIsVideoCachedOk = true;
                if (canStartPlay() && !mDidStartPlay) {
                    startPlay();
                }
            }
            break;
        case MSG_ID_VIDEO_PROXY_RECONNECT:
            if (/*mMediaPlayerShiftStreamToFile
                    &&*/ mMediaPlayerStreaming
                    && mVideoProxyServer != null
                    && mVideoLoader.isCacheCompleted()) {
                shiftPlayStreamToFile();
            }
            break;
        case MSG_ID_INFO_PLAY_DATA_UPDATE:
            // レイアウトが整わないうちに設定してもたまに狂う場合があるのでワンテンポ遅らせる
            mHandler.sendEmptyMessage(MSG_ID_SET_VIDEO_VIEW_LAYOUT);
            super.handleMessage(msg);
            break;
        case MSG_ID_VIDEO_TRACK_LAGGING:
            if (!mShownVideoTrackLagging) {
                showToastAtCorner(mContext,
                        R.string.toast_video_track_lagging,
                        Toast.LENGTH_LONG);
                mShownVideoTrackLagging = true;
            }
            break;
        case MSG_ID_BAD_INTERLEAVING:
            if (!mShownBadInterleaving) {
                showToastAtCorner(mContext,
                        R.string.toast_bad_interleaving,
                        Toast.LENGTH_LONG);
                mShownBadInterleaving = true;
            }
            break;
        case MSG_ID_SET_VIDEO_VIEW_LAYOUT:
            // Messageが複数あったら一番最後のタイミングで実行する
            if (!mHandler.hasMessages(MSG_ID_SET_VIDEO_VIEW_LAYOUT)) {
                setVideoViewLayout();
            }
            break;
        default:
            super.handleMessage(msg);
            break;
        }
        return true;
    }

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

        if (DEBUG_LOGD) {
            Log.d(LOG_TAG, "MediaPlayerFragment onCreate");
        }

        mIsVideoProxyOk = false;
        mIsVideoViewSizeOk = false;

        mHadError = false;

        mShownVideoTrackLagging = false;
        mShownBadInterleaving = false;

        mFullscreen16_9 = mSharedPreferences.getBoolean(
                getString(R.string.pref_key_16_9_fullscreen), false);
        mMediaPlayerStreaming = mSharedPreferences.getBoolean(
                getString(R.string.pref_key_mediaplayer_streaming),
                true);
        mMediaPlayerShiftStreamToFile = mSharedPreferences.getBoolean(
                getString(R.string.pref_key_mediaplayer_shift_stream_to_file),
                true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_mediaplayer, container, false);

        mVideoFrame = ViewUtil.findViewById(view, R.id.video_frame);
        mVideoView = ViewUtil.findViewById(view, R.id.video);

        mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
//              mMediaPlayer = mp;
//              mp.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
//                  @Override
//                  public void onSeekComplete(MediaPlayer mp) {
//                      // シークバー再有効化
//                      if (mHandler != null) {
//                          mHandler.sendEmptyMessage(MSG_ID_ENABLE_SEEK_BAR);
//                      }
//                  }
//              });
//              mp.setOnInfoListener(new MediaPlayer.OnInfoListener() {
//                  @Override
//                  public boolean onInfo(MediaPlayer mp, int what, int extra) {
//                      if (DEBUG_LOGD) {
//                          Log.d(LOG_TAG, Log.buf().append("MediaPlayer onInfo: what=")
//                                  .append(what).append(" extra=")
//                                  .append(extra).toString());
//                      }
//                      switch (what) {
//                          case MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING:
//                              if (mHandler != null) {
//                                  mHandler.sendEmptyMessage(MSG_ID_VIDEO_TRACK_LAGGING);
//                              }
//                              break;
//                          case MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING:
//                                if (mHandler != null) {
//                                    mHandler.sendEmptyMessage(MSG_ID_BAD_INTERLEAVING);
//                                }
//                              break;
//                      }
//                      return false;
//                  }
//              });
                if (mp.getVideoWidth() != 0 && mp.getVideoHeight() != 0) {
                    Handler handler = mHandler;
                    handler.sendEmptyMessage(MSG_ID_INFO_PLAY_DATA_UPDATE);
                } else {
//                  // OnVideoSizeChangedListenerの設定はVideoViewの内部リスナ上書きするのでNG
//                  // 仕方がないので一定時間待ってリトライ
//                  mHandler.sendEmptyMessageDelayed(
//                          MSG_ID_WAIT_VIDEO_SIZE_GET, 1000L);
                }
            }
        });
        mVideoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
            @Override
            public boolean onError(MediaPlayer mp, int what, int extra) {
                if (DEBUG_LOGD) {
                    Log.d(LOG_TAG, Log.buf().append("MediaPlayer onError: mp=")
                            .append(mp.toString())
                            .append(" what=").append(what)
                            .append(" extra=").append(extra)
                            .toString());
                }

                mHadError = true;
                // エラー状態でサイズ取得しようとすると例外飛ぶことがあるっぽいのでMessageキャンセル
                Handler handler = mHandler;
//                handler.removeMessages(MSG_ID_WAIT_VIDEO_SIZE_GET);
                handler.removeMessages(MSG_ID_INFO_PLAY_DATA_UPDATE);
//              if (mInfoPlayData.getTextBuilder().length() == 0) {
//                  mHandler.sendEmptyMessage(MSG_ID_INFO_PLAY_DATA_UPDATE);
//              }

                PlayerActivity playerActivity = getPlayerActivity();
                if (playerActivity != null) {
                    // エラーダイアログの多重表示はしない
                    if (playerActivity.canShowErrorDialog()) {
                        String errorMessage;
                        switch (what) {
                        case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
                            errorMessage = getString(R.string.errormessage_mediaplayer_streaming);
                            break;
                        case MediaPlayer.MEDIA_ERROR_UNKNOWN:
                            errorMessage = getString(R.string.errormessage_mediaplayer_unknown);
                            break;
                        default:
                            Log.d(LOG_TAG, Log.buf()
                                    .append("MediaPlayer onError: unexpected argument=")
                                    .append(what).append(',').append(extra).toString());
                            errorMessage = getString(R.string.errormessage_mediaplayer_unknown);
                            break;
                        }
                        errorMessage += getString(R.string.dialog_text_suffix_player_auto_close);

                        DialogInterface.OnClickListener listener =
                            new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                                PlayerActivity playerActivity = getPlayerActivity();
                                if (playerActivity != null) {
                                    switch (which) {
                                    case DialogInterface.BUTTON_POSITIVE:
                                        // Fragmentの差し替え
                                        Handler parentHandler = playerActivity.getHandler();
                                        parentHandler.removeMessages(MSG_ID_AUTO_CLOSE);
                                        switchToFFmpeg();
                                        break;
                                    case DialogInterface.BUTTON_NEGATIVE:
                                        playerActivity.finish();
                                        break;
                                    default:
                                        if (DEBUG_LOGD) {
                                            Log.d(LOG_TAG, Log.buf()
                                                    .append("NicoroMediaPlayer ErrorDialog onClick: unexpected argument=")
                                                    .append(which).toString());
                                        }
                                        break;
                                    }
                                }
                            }
                        };
                        playerActivity.onShowErrorDialog(new AlertDialog.Builder(playerActivity)
                            .setTitle(
                                R.string.dialog_title_mediaplayer_error)
                            .setMessage(errorMessage)
                            .setCancelable(false)
                            .setPositiveButton(
                                    R.string.dialog_button_mediaplayer_error_start_ffmpeg,
                                    listener)
                            .setNegativeButton(
                                    R.string.dialog_button_mediaplayer_error_close,
                                    listener)
                            .show());
                    }
                }

                return true;
            }
        });
        mVideoView.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
            @Override
            public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
                if (width != 0 && height != 0) {
                    Handler handler = mHandler;
                    handler.sendEmptyMessage(
                            MSG_ID_INFO_PLAY_DATA_UPDATE);
                }
            }
        });
        mVideoView.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
            @Override
            public void onSeekComplete(MediaPlayer mp) {
                // シークバー再有効化
                Handler handler = mHandler;
                handler.sendEmptyMessage(MSG_ID_ENABLE_SEEK_BAR);
            }
        });
        mVideoView.setOnInfoListener(new MediaPlayer.OnInfoListener() {
            @Override
            public boolean onInfo(MediaPlayer mp, int what, int extra) {
                if (DEBUG_LOGD) {
                    Log.d(LOG_TAG, Log.buf().append("MediaPlayer onInfo: what=")
                            .append(what).append(" extra=")
                            .append(extra).toString());
                }
                Handler handler = mHandler;
                switch (what) {
                    case MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING:
                        handler.sendEmptyMessage(MSG_ID_VIDEO_TRACK_LAGGING);
                        break;
                    case MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING:
                        handler.sendEmptyMessage(MSG_ID_BAD_INTERLEAVING);
                        break;
                }
                return false;
            }
        });
        mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                Handler handler = mHandler;
                handler.sendEmptyMessage(MSG_ID_PLAY_FINISHED);
            }
        });

        mMessageView = ViewUtil.findViewById(view, R.id.message_view);
        if (getPlayerActivity().getEnableHardwareAccelerated()) {
            // XXX 常にsoftware layer使用
            APILevelWrapper api = APILevelWrapper.createInstance();
            api.setLayerType(mMessageView, View.LAYER_TYPE_SOFTWARE, null);
        }
        mMessageView.setCallback(this);

//        setVideoViewLayout();

        return view;
    }

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

        initializeVideoLoader();
    }

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

    @Override
    public void onDestroyImplPre() {
        mVideoView.stopPlayback();
        mVideoView.release();
//        mMediaPlayer = null;
        if (mVideoProxyServer != null) {
            mVideoProxyServer.stopProxy();
            mVideoProxyServer = null;
        }
        super.onDestroyImplPre();
    }

    @Override
    protected void onOrientationChanged(int orientation) {
        // 回転のonConfigurationChangedでサイズ設定しないと
        // うまく反映されないAndroidのバージョンがある模様
        setVideoViewLayout();
    }

    @Override
    public void onParentScreenLayout(int width, int height) {
        if (width > 0 && height > 0) {
            // 回転直後のレイアウトサイズ変更直後に設定してもたまに狂う場合があるのでワンテンポ遅らせる
            mHandler.sendEmptyMessage(MSG_ID_SET_VIDEO_VIEW_LAYOUT);
        }
    }

    @Override
    protected boolean canStartPlay() {
        if (mStateManager.isStarting()) {
            return ((mIsVideoDownloadOk || (mIsVideoProxyOk && mIsVideoCachedOk))
                    && mMessageChatController.isMessageDataOk()
                    && mIsVideoViewSizeOk);
        } else if (mStateManager.wasCreated() && !mStateManager.wasDestroyed()) {
            // バックグラウンド中
            return ((mIsVideoDownloadOk || (mIsVideoProxyOk && mIsVideoCachedOk))
                    && mMessageChatController.isMessageDataOk());
        } else {
            return false;
        }

//        return ((mStateManager.isResuming() || mDidStartPlay)
//                && (mIsVideoDownloadOk || (mIsVideoProxyOk && mIsVideoCachedOk))
//                && mMessageChatController.isMessageDataOk()
//                && mIsVideoViewSizeOk);
    }

    @Override
    protected void startPlay() {
        super.startPlay(mThumbInfo);

        if (mMediaPlayerStreaming && !mVideoLoader.isCacheCompleted()) {
            assert mVideoProxyServer != null;
            mVideoView.setVideoURI(mVideoProxyServer.getUri());
        } else {
            String file = mVideoLoader.getFilePath();
            mVideoView.setVideoPath(file);
        }

        mVideoView.start();
        if (DEBUG_LOGD) {
            Log.d(LOG_TAG, "VideoView start");
        }

        Message message = mHandler.obtainMessage(MSG_ID_MESSAGE_DRAW_MESSAGE);
        mHandler.sendMessageDelayed(message, 33L);

        postStartPlayIfIsRestored();
    }

    @Override
    public StringBuilder appendCurrentPlayTime(StringBuilder builder) {
        getCurrentPositionVideoPlay(mRationalCurrentPlayTime);
        final long posNum = mRationalCurrentPlayTime.num;
        final int posDen = mRationalCurrentPlayTime.den;
        return appendCurrentPlayTimeCommon(builder, posNum, posDen);
    }

    @Override
    public boolean hasTotalPlayTime() {
        return true;
    }

    @Override
    public void getCurrentPositionVideoPlay(Rational rational) {
        if (mVideoView == null) {
            // viewの初期化前に実行される可能性がある？
            rational.num = 0;
        } else {
            rational.num = mVideoView.getCurrentPosition();
        }
        rational.den = 1000;    // ms
    }
    @Override
    protected void getCurrentPositionAudioPlay(Rational rational) {
        // Videoと同じ
        getCurrentPositionVideoPlay(rational);
    }
    @Override
    protected void getCurrentPositionVideoDecode(Rational rational) {
        // playの時間を代わりに使う
        getCurrentPositionVideoPlay(rational);
    }
    @Override
    protected void getCurrentPositionAudioDecode(Rational rational) {
        // playの時間を代わりに使う
        getCurrentPositionAudioPlay(rational);
    }

    @Override
    protected boolean switchPausePlay() {
        if (mVideoView.isPlaying()) {
            pausePlay();
        } else {
            restartPlay();
        }
        setButtonPauseImage();
        return true;
    }

    @Override
    protected void pausePlay() {
//      mIconPause.setVisibility(View.VISIBLE);
        mVideoView.pause();
    }

    @Override
    protected void restartPlay() {
//      mIconPause.setVisibility(View.INVISIBLE);
        mVideoView.start();
    }

    @Override
    protected boolean isPausePlay() {
        return !mVideoView.isPlaying();
    }

    @Override
    protected void seekBySecond(int second) {
        seekBySecondCommon(second);
        if (mVideoView == null) {
            // VideoViewの準備ができていない場合は、この場でシークバー有効化
            Handler handler = mHandler;
            handler.sendEmptyMessage(MSG_ID_ENABLE_SEEK_BAR);
        } else {
            mVideoView.seekTo(second * 1000);
        }
    }

    @Override
    protected VideoLoaderInterface.EventListener createVideoLoaderEventListener() {
        return new VideoLoaderInterface.EventListener() {
            @Override
            public void onStarted(VideoLoaderInterface streamLoader) {
                Handler handler = mHandler;
                handler.sendEmptyMessage(MSG_ID_VIDEO_DOWNLOAD_STARTED);
            }
            @Override
            public void onCached(VideoLoaderInterface videoLoader) {
                Handler handler = mHandler;
                handler.sendEmptyMessage(MSG_ID_VIDEO_CACHED);
            }
            @Override
            public void onFinished(VideoLoaderInterface videoLoader) {
                Handler handler = mHandler;
                handler.sendEmptyMessage(MSG_ID_VIDEO_DOWNLOAD_FINISHED);
            }
            @Override
            public void onOccurredError(VideoLoaderInterface videoLoader, String errorMessage) {
                Handler handler = mHandler;
                handler.obtainMessage(MSG_ID_VIDEO_OCCURRED_ERROR,
                        errorMessage).sendToTarget();
            }
            @Override
            public void onNotifyProgress(int num, int den) {
                Handler handler = mHandler;
//                try {
//                    if (mVideoView == null || !mVideoView.isPlaying()) {
                        handler.removeMessages(MSG_ID_VIDEO_NOTIFY_PROGRESS);
                        handler.obtainMessage(MSG_ID_VIDEO_NOTIFY_PROGRESS,
                                num, den).sendToTarget();
//                    }
//                } catch (IllegalStateException e) {
//                    // Error状態でisPlaying呼ぶと例外飛ぶ
//                    Log.e(LOG_TAG, e.toString(), e);
//                }
            }
            @Override
            public void onRestarted(VideoLoaderInterface streamLoader) {
                // 何もしない
            }
        };
    }

    @Override
    public StringBuilder appendVideoResolution(StringBuilder builder) {
        // 初期化前に実行される可能性が微妙にあるのでnullチェック
//      MediaPlayer mediaPlayer = mMediaPlayer;
//      if (mediaPlayer != null && !mHadError) {
        MediaSurfaceView videoView = mVideoView;
        if (videoView != null) {
//            // まだIllegalStateException出る場合がある
//            try {
//              int videoWidth = mediaPlayer.getVideoWidth();
//              int videoHeight = mediaPlayer.getVideoHeight();
                int videoWidth = videoView.getVideoWidth();
                int videoHeight = videoView.getVideoHeight();
                if (videoWidth != 0 || videoHeight != 0) {
                    builder.append(videoWidth)
                        .append('×')
                        .append(videoHeight);
                }
//            } catch (IllegalStateException e) {
//                Log.e(LOG_TAG, e.toString(), e);
//            }
        }
        return builder;
    }

    @Override
    public StringBuilder appendPlayerInfo(StringBuilder builder) {
        return builder.append(getString(R.string.info_play_data_mediaplayer));
    }

    @Override
    public void drawMessageView(MessageView messageView, Canvas canvas) {
        canvas.drawColor(0x00000000);
//      if (mVideoView.isPlaying()) {
        if (mMessageChatController.isMessageDataOk()) {
            int vpos = getVpos();
            mMessageChatController.drawMessage(canvas,
                    vpos, messageView.getWidth(), messageView.getHeight(),
                    getMessageDisable());
        }
    }

    @Override
    protected int getVpos() {
        return mVideoView.getCurrentPosition() / 10;
    }

    private void setVideoViewLayout() {
        PlayerActivity playerActivity = getPlayerActivity();
        if (playerActivity == null) {
            return;
        }
        int orientation = getResources().getConfiguration().orientation;
        RelativeLayout parentScreen = playerActivity.getParentScreen();
        int displayWidth = parentScreen.getWidth();
        int displayHeight = parentScreen.getHeight();
        if (DEBUG_LOGD) {
            Log.d(LOG_TAG, Log.buf().append("MediaPlayerFragment: orientation=")
                    .append(orientation)
                    .append(" displayWidth=").append(displayWidth)
                    .append(" displayHeight=").append(displayHeight)
                    .toString());
        }
        if (displayWidth == 0 || displayHeight == 0) {
            return;
        }
        // 機種によっては起動直後や回転直後に正確な値が取れないので対策
        if ((orientation == Configuration.ORIENTATION_PORTRAIT
                && displayWidth > displayHeight)
                || (orientation == Configuration.ORIENTATION_LANDSCAPE
                        && displayWidth < displayHeight)) {
            return;
        }

//        MediaPlayer mediaPlayer = mMediaPlayer;
//        int videoWidth = 0;
//        int videoHeight = 0;
//        if (mediaPlayer != null && !mHadError) {
//            try {
//                videoWidth = mediaPlayer.getVideoWidth();
//                videoHeight = mediaPlayer.getVideoHeight();
//            } catch (IllegalStateException e) {
//                Log.e(LOG_TAG, e.toString(), e);
//            }
//        }
        int videoWidth = mVideoView.getVideoWidth();
        int videoHeight = mVideoView.getVideoHeight();
        if (videoWidth == 0 || videoHeight == 0) {
            // 仮で値設定
            mComputeVideoDisplaySize.compute(
                    displayWidth, displayHeight,
                    displayWidth, displayHeight,
                    orientation, mFullscreen16_9);
            videoWidth = mComputeVideoDisplaySize.getWidth();
            videoHeight = mComputeVideoDisplaySize.getHeight();
        }

        if (displayWidth == mLastDisplayWidth && displayHeight == mLastDisplayHeight
                && videoWidth == mLastVideoWidth && videoHeight == mLastVideoHeight) {
            // 前回演算と入力値がまったく同じ場合は処理省略
            return;
        }
        mLastDisplayWidth = displayWidth;
        mLastDisplayHeight = displayHeight;
        mLastVideoWidth = videoWidth;
        mLastVideoHeight = videoHeight;

        mComputeVideoDisplaySize.compute(
                videoWidth, videoHeight,
                displayWidth, displayHeight,
                orientation, mFullscreen16_9);
        int width = mComputeVideoDisplaySize.getWidth();
        int height = mComputeVideoDisplaySize.getHeight();
        int surfaceWidth;
        int surfaceHeight;
        int tempSurfaceWidth = (height * videoWidth + (videoHeight - 1)) / videoHeight;
        int tempSurfaceHeight = (width * videoHeight + (videoWidth - 1)) / videoWidth;
        if (tempSurfaceWidth > width) {
            surfaceWidth = width;
            surfaceHeight = tempSurfaceHeight;
            assert surfaceHeight <= height;
        } else {
            surfaceWidth = tempSurfaceWidth;
            surfaceHeight = height;
        }

        mVideoView.setSurfaceSize(surfaceWidth, surfaceHeight);
        ViewGroup.LayoutParams params = mVideoFrame.getLayoutParams();
        params.width = width;
        params.height = height;
        mVideoFrame.requestLayout();
        mIsVideoViewSizeOk = true;
        if (DEBUG_LOGD) {
            Log.d(LOG_TAG, Log.buf().append("MediaPlayerFragment: VideoArea width=").append(width)
                    .append(" height=").append(height)
                    .append(", Surface width=").append(surfaceWidth)
                    .append(" height=").append(surfaceHeight).toString());
        }

        onVideoViewSizeChanged(width, height);
    }

    /**
     * ストリーム再生からファイル再生へ移行する
     */
    private void shiftPlayStreamToFile() {
        if (mShowHintToast) {
            showToastAtCorner(mContext,
                    R.string.toast_shift_stream_to_file, Toast.LENGTH_SHORT);
        }

        int currentMs = mVideoView.getCurrentPosition();
        boolean isPlaying = mVideoView.isPlaying();

//        mVideoView.stopPlayback();
        String file = mVideoLoader.getFilePath();
        // XXX まれにsetVideoPathでANRが起きるが、Mainスレッド以外で動作させる訳にもいかないのでどうしようもない
        mVideoView.setVideoPath(file);
        seekBySecond(currentMs / 1000); // start前にseek実行
        mVideoView.start();
        mVideoProxyServer.stopProxy();
        mVideoProxyServer = null;
        if (!isPlaying) {
            mVideoView.pause();
        }
//        // data再設定後はVideoViewのサイズが狂うときがある？ので
//        // MessageViewを手動調整
//        if (mVideoViewWidth > 0 && mVideoViewHeight > 0) {
//            RelativeLayout.LayoutParams param =
//                (RelativeLayout.LayoutParams)
//                mMessageView.getLayoutParams();
//            assert param != null;
//            param.width = mVideoViewWidth;
//            param.height = mVideoViewHeight;
//            param.addRule(RelativeLayout.ALIGN_RIGHT, 0);
//            mMessageView.requestLayout();
//        }
    }

    private static void showToastAtCorner(Context context,
            int resId, int duration) {
        Toast toast = Toast.makeText(context,
                resId, duration);
        toast.setGravity(Gravity.BOTTOM | Gravity.RIGHT, 0, 0);
        toast.show();
    }

    private void switchToFFmpeg() {
        PlayerActivity playerActivity = getPlayerActivity();
        if (playerActivity == null) {
            return;
        }
        Handler parentHandler = playerActivity.getHandler();
        parentHandler.removeMessages(MSG_ID_INFO_TIME_UPDATE);
        parentHandler.removeMessages(MSG_ID_NOTIFICATION_TIME_UPDATE);
        playerActivity.setPlayerFragment(null);
        FFmpegPlayerFragment newFragment = new FFmpegPlayerFragment();
        newFragment.setArguments(getArguments());
        newFragment.moveThumbInfoFrom(MediaPlayerFragment.this);
        newFragment.moveVideoLoaderFrom(MediaPlayerFragment.this);
        newFragment.moveMessagesFrom(MediaPlayerFragment.this);
        newFragment.moveConfigureNgClientFrom(MediaPlayerFragment.this);
        replacePlayerFragment(newFragment, false);
        finishFragment();
    }
}
