package jp.sourceforge.nicoro;

import java.util.LinkedList;


import static jp.sourceforge.nicoro.Log.LOG_TAG;
import jp.sourceforge.nicoro.R;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Canvas;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.VideoView;

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

	private static final int MSG_ID_VIDEO_DOWNLOAD_FINISHED = MSG_ID_SUB_OFFSET + 0;
	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 boolean mIsVideoDownloadOk;
	
	private VideoView mVideoView;
	private MessageView mMessageView;
//	private ImageView mIconPause;
	private MediaPlayer mMediaPlayer;
	
	public NicoroMediaPlayer() {
		mHandler = new MessageHandler() {
			@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;
				}
				switch (msg.what) {
				case MSG_ID_VIDEO_DOWNLOAD_FINISHED:
					mIsVideoDownloadOk = true;
					if (canStartPlay()) {
						startPlay();
					}
					break;
				case MSG_ID_MESSAGE_DRAW_MESSAGE:
					if (!isFinishing()) {
						mMessageView.invalidate();
						
						Message message = mHandler.obtainMessage(
								MSG_ID_MESSAGE_DRAW_MESSAGE);
						mHandler.sendMessageDelayed(message, 33L);
					}
					break;
				case MSG_ID_WAIT_VIDEO_SIZE_GET:
					if (mMediaPlayer != null) {
						if (mMediaPlayer.getVideoWidth() != 0
								|| mMediaPlayer.getVideoHeight() != 0) {
							mHandler.sendEmptyMessage(
									MSG_ID_INFO_PLAY_DATA_UPDATE);
						} else {
							mHandler.sendEmptyMessageDelayed(
									MSG_ID_WAIT_VIDEO_SIZE_GET, 1000L);
						}
					}
					break;
				default:
					super.handleMessage(msg);
					break;
				}
			}
		};
	}
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
        if (DEBUG_LOGD) {
        	Log.d(LOG_TAG, "NicoroMediaPlayer onCreate");
        }
		
        mIsVideoDownloadOk = false;
        
		setContentView(R.layout.nicoro_mediaplayer);
		mVideoView = (VideoView) findViewById(R.id.video);
		DisplayMetrics metrics = new DisplayMetrics();
		getWindowManager().getDefaultDisplay().getMetrics(metrics);
		mVideoView.getLayoutParams().width =
//			(int) (metrics.heightPixels * 4 / 3 / metrics.density);
			(int) (metrics.heightPixels * 4 / 3);
		mVideoView.getLayoutParams().height =
//			(int) (metrics.heightPixels / metrics.density);
			(int) (metrics.heightPixels);
		mVideoView.requestLayout();
		
		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);
						}
					}
				});
				if (mp.getVideoWidth() != 0 || mp.getVideoHeight() != 0) {
					mHandler.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 (mInfoPlayData.getTextBuilder().length() == 0) {
					mHandler.sendEmptyMessage(MSG_ID_INFO_PLAY_DATA_UPDATE);
				}
				
				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;
				}
				
				DialogInterface.OnClickListener listener =
					new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						dialog.dismiss();
						switch (which) {
						case DialogInterface.BUTTON_POSITIVE:
							Intent intent = new Intent(getIntent());
							intent.setClass(getApplicationContext(),
									NicoroFFmpegPlayer.class);
							startActivityIfNeeded(intent, 0);
							finish();
							break;
						case DialogInterface.BUTTON_NEGATIVE:
							finish();
							break;
						default:
							if (DEBUG_LOGD) {
								Log.d(LOG_TAG, Log.buf()
										.append("NicoroMediaPlayer ErrorDialog onClick: unexpected argument=")
										.append(which).toString());
							}
							break;
						}
					}
				};
				AlertDialog.Builder alertDialogBuilder =
					new AlertDialog.Builder(NicoroMediaPlayer.this);
				alertDialogBuilder.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.setOnTouchListener(new View.OnTouchListener() {
//			@Override
//			public boolean onTouch(View v, MotionEvent event) {
//				if (event.getAction() == MotionEvent.ACTION_DOWN) {
//					return switchPause();
//				}
//				return false;
//			}
//		});
		
//		mIconPause = (ImageView) findViewById(R.id.icon_pause);
//		mIconPause.setAlpha(192);
		
		mMessageView = (MessageView) findViewById(R.id.message_view);
		mMessageView.setCallback(this);
		initializeView();
		
        Intent intent = getIntent();
        mVideoLoader = createVideoLoader(intent, getApplicationContext());
        if (mVideoLoader != null) {
        	mVideoLoader.setEventListener(new VideoLoader.EventListener() {
				@Override
				public void onCached(VideoLoader videoLoader) {
					// nothing
				}
				@Override
				public void onFinished(VideoLoader videoLoader) {
					if (mHandler != null) {
						mHandler.sendEmptyMessage(MSG_ID_VIDEO_DOWNLOAD_FINISHED);
					}
				}
				@Override
				public void onOccurredError(VideoLoader videoLoader, String errorMessage) {
					if (mHandler != null) {
						Message message = mHandler.obtainMessage(MSG_ID_VIDEO_OCCURRED_ERROR, errorMessage);
						mHandler.sendMessage(message);
					}
				}
				@Override
				public void onNotifyProgress(int num, int den) {
					if (mHandler != null) {
						if (mVideoView == null || !mVideoView.isPlaying()) {
							mHandler.removeMessages(MSG_ID_VIDEO_NOTIFY_PROGRESS);
							Message message = mHandler.obtainMessage(MSG_ID_VIDEO_NOTIFY_PROGRESS, num, den);
							mHandler.sendMessage(message);
						}
					}
				}
        	});
        	// 最初にダウンロード要求
        	mVideoLoader.startLoad();
        }
        
	}

	@Override
	protected void onDestroy() {
		mVideoView.stopPlayback();
		super.onDestroy();
		mMediaPlayer = null;
		mVideoView = null;
		mMessageView = null;
	}
	
	@Override
	protected boolean canStartPlay() {
		return mIsVideoDownloadOk && mMessageData.mIsMessageOk && mMessageDataFork.mIsMessageOk;
	}
	
	@Override
	protected void startPlay() {
		super.startPlay();
    	
		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);
	}
	
	@Override
	protected StringBuilder appendCurrentPlayTime(StringBuilder builder) {
		getCurrentPositionVideoPlay(mRatinalCurrentPlayTime);
		final int posNum = mRatinalCurrentPlayTime.num;
		final int posDen = mRatinalCurrentPlayTime.den;
		return appendCurrentPlayTimeCommon(builder, posNum, posDen);
	}
	
	@Override
	protected void getCurrentPositionVideoPlay(Rational rational) {
		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);
		mVideoView.seekTo(second * 1000);
	}
	
	@Override
	protected StringBuilder appendVideoResolution(StringBuilder builder) {
		if (mMediaPlayer != null) {
			int videoWidth = mMediaPlayer.getVideoWidth();
			int videoHeight = mMediaPlayer.getVideoHeight();
			if (videoWidth != 0 || videoHeight != 0) {
				builder.append(videoWidth)
					.append('×')
					.append(videoHeight);
			}
		}
		return builder;
	}
	
	@Override
	protected 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 (mMessageData.mIsMessageOk) {
			int vpos = mVideoView.getCurrentPosition() / 10;
			drawMessage(canvas,
					mMessageData,
	        		mMessageDataFork,
					vpos, messageView.getWidth(), messageView.getHeight());
		}
	}
}
