package com.yidianling.uikit.business.session.activity;

import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import androidx.appcompat.app.ActionBar;

import com.netease.nimlib.sdk.AbortableFuture;
import com.netease.nimlib.sdk.NIMClient;
import com.netease.nimlib.sdk.Observer;
import com.netease.nimlib.sdk.RequestCallback;
import com.netease.nimlib.sdk.msg.MsgService;
import com.netease.nimlib.sdk.msg.MsgServiceObserve;
import com.netease.nimlib.sdk.msg.attachment.VideoAttachment;
import com.netease.nimlib.sdk.msg.constant.AttachStatusEnum;
import com.netease.nimlib.sdk.msg.model.AttachmentProgress;
import com.netease.nimlib.sdk.msg.model.IMMessage;
import com.ydl.ydlcommon.app.Apm;
import com.yidianling.im.R;
import com.yidianling.nimbase.common.ToastHelper;
import com.yidianling.nimbase.common.activity.ToolBarOptions;
import com.yidianling.nimbase.common.activity.UI;
import com.yidianling.nimbase.common.util.file.FileUtil;
import com.yidianling.nimbase.common.util.sys.TimeUtil;
import com.yidianling.uikit.custom.config.YDLToolBarOptions;

/**
 * 视频播放界面
 * <p/>
 * Created by huangjun on 2015/4/11.
 */
public class WatchVideoActivity extends UI implements Callback {
    public static final String INTENT_EXTRA_DATA = "EXTRA_DATA";
    public static final String INTENT_EXTRA_MENU = "EXTRA_MENU";

    // player

    private MediaPlayer mediaPlayer;

    // context

    private Handler handlerTimes = new Handler();

    private ActionBar actionBar;

    private IMMessage message;

    // view

    private SurfaceView surfaceView;

    private SurfaceHolder surfaceHolder;

    private View videoIcon;

    private View downloadLayout;

    private View downloadProgressBackground;

    private View downloadProgressForeground;

    private TextView downloadProgressText;

    protected TextView fileInfoTextView;

    private TextView playTimeTextView;

    // state
    private boolean isShowMenu = true;

    private boolean isSurfaceCreated = false;

    protected String videoFilePath;

    protected long videoLength = 0;

    private float lastPercent;

    private int playState = PLAY_STATE_STOP;

    private final static int PLAY_STATE_PLAYING = 1;

    private final static int PLAY_STATE_STOP = 2;

    private final static int PLAY_STATE_PAUSE = 3;

    // download control
    private boolean downloading;
    private ImageView downloadBtn;
    private AbortableFuture downloadFuture;

    public static void start(Context context, IMMessage message) {
        Intent intent = new Intent();
        intent.putExtra(WatchVideoActivity.INTENT_EXTRA_DATA, message);
        intent.setClass(context, WatchVideoActivity.class);
        context.startActivity(intent);
    }

    public static void start(Context context, IMMessage message, boolean isShowMenu) {
        Intent intent = new Intent();
        intent.putExtra(WatchVideoActivity.INTENT_EXTRA_DATA, message);
        intent.putExtra(INTENT_EXTRA_MENU, isShowMenu);
        intent.setClass(context, WatchVideoActivity.class);
        context.startActivity(intent);
    }

    public ToolBarOptions statusBarOptions(){
        YDLToolBarOptions ydlToolBarOptions = new YDLToolBarOptions();
        ydlToolBarOptions.statusBarColor = "#000000";
        ydlToolBarOptions.statusBarDarkMode = false;
        return ydlToolBarOptions;
    }

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

        setContentView(R.layout.im_nim_watch_video_activity);

        ToolBarOptions options = new YDLToolBarOptions();
        setToolBar(R.id.toolbar, options);

        parseIntent();
        findViews();
        initActionbar();

        showVideoInfo();

        registerObservers(true);
        download();
    }

    public void onResume() {
        super.onResume();
        mediaPlayer = new MediaPlayer();

        if (isSurfaceCreated) {
            play();
        }
    }

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

        stopMediaPlayer();
    }

    @Override
    public void onBackPressed() {
        stopDownload();
        super.onBackPressed();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        registerObservers(false);
    }

    private void parseIntent() {
        message = (IMMessage) getIntent().getSerializableExtra(INTENT_EXTRA_DATA);
        setTitle(String.format("视频发送于%s", TimeUtil.getDateString(message.getTime())));
        isShowMenu = getIntent().getBooleanExtra(INTENT_EXTRA_MENU, false);
    }

    private void findViews() {
        downloadLayout = findViewById(R.id.layoutDownload);
        downloadProgressBackground = findViewById(R.id.downloadProgressBackground);
        downloadProgressForeground = findViewById(R.id.downloadProgressForeground);
        downloadProgressText = (TextView) findViewById(R.id.downloadProgressText);
        videoIcon = findViewById(R.id.videoIcon);

        surfaceView = (SurfaceView) findViewById(R.id.videoView);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        surfaceHolder.addCallback(this);

        playTimeTextView = (TextView) findViewById(R.id.lblVideoTimes);
        playTimeTextView.setVisibility(View.INVISIBLE);
        fileInfoTextView = (TextView) findViewById(R.id.lblVideoFileInfo);
        playTimeTextView.setVisibility(View.INVISIBLE);

        downloadBtn = (ImageView) findViewById(R.id.control_download_btn);
        downloadBtn.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (downloading) {
                    stopDownload();
                } else {
                    download();
                }
                downloadBtn.setImageResource(downloading ? R.drawable.im_nim_icon_download_pause : R.drawable.im_nim_icon_download_resume);
            }
        });

        actionBar = getSupportActionBar();
    }

    private void initActionbar() {
        TextView menuBtn = findView(R.id.actionbar_menu);
        if (isShowMenu) {
            menuBtn.setVisibility(View.VISIBLE);
            menuBtn.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    WatchPicAndVideoMenuActivity.startActivity(WatchVideoActivity.this, message);
                }
            });
        } else {
            menuBtn.setVisibility(View.GONE);
        }
    }

    private void initVideoSize() {
        if (mediaPlayer == null) {
            return;
        }
        // 视频宽高
        int width = mediaPlayer.getVideoWidth();
        int height = mediaPlayer.getVideoHeight();

        if (width <= 0 || height <= 0) {
            return;
        }

        // 屏幕宽高
        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        int screenWidth = dm.widthPixels;
        int screenHeight = dm.heightPixels;

        int videoRatio = width / height;
        int screenRatio = screenWidth / screenHeight;

        if (screenRatio > videoRatio) {
            int newHeight = screenHeight;
            int newWidth = screenHeight * width / height;
            RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
                    newWidth, newHeight);
            int margin = (screenWidth - newWidth) / 2;
            layoutParams.setMargins(margin, 0, margin, 0);
            surfaceView.setLayoutParams(layoutParams);
        } else {
            int newWidth = screenWidth;
            int newHeight = screenWidth * height / width;
            RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
                    newWidth, newHeight);
            int margin = (screenHeight - newHeight) / 2;
            layoutParams.setMargins(0, margin, 0, margin);
            surfaceView.setLayoutParams(layoutParams);
        }
    }

    /**
     * ****************************** MediaPlayer Start ********************************
     */
    private void stopMediaPlayer() {
        if (mediaPlayer != null) {
            if (mediaPlayer.isPlaying()) {
                mediaPlayer.stop();
            }
            mediaPlayer.reset();
            mediaPlayer.release();
            mediaPlayer = null;
            actionBar.show();

        }
    }

    /**
     * 处理视频播放时间
     */
    private Runnable timeRunnable = new Runnable() {
        public void run() {
            if (mediaPlayer != null && mediaPlayer.isPlaying()) {
                playState = PLAY_STATE_PLAYING;

                if (videoLength <= 0) {
                    playTimeTextView.setVisibility(View.INVISIBLE);
                } else {
                    // 由于mediaPlayer取到的时间不统一,采用消息体中的时间
                    int leftTimes = (int) (videoLength * 1000 - mediaPlayer.getCurrentPosition());
                    if (leftTimes < 0) {
                        leftTimes = 0;
                    }

                    playTimeTextView.setVisibility(View.VISIBLE);
                    long seconds = TimeUtil.getSecondsByMilliseconds(leftTimes);
                    playTimeTextView.setText(TimeUtil.secToTime((int) seconds));
                    handlerTimes.postDelayed(this, 1000);
                }

            }
        }
    };

    protected void pauseVideo() {
        videoIcon.setVisibility(View.VISIBLE);
        if (mediaPlayer != null && mediaPlayer.isPlaying()) {
            mediaPlayer.pause();
            handlerTimes.removeCallbacks(timeRunnable);
            playState = PLAY_STATE_PAUSE;
            actionBar.show();
        }
    }

    protected void resumeVideo() {
        videoIcon.setVisibility(View.GONE);
        if (mediaPlayer != null) {
            if (!mediaPlayer.isPlaying()) {
                mediaPlayer.start();
                playState = PLAY_STATE_PLAYING;
                handlerTimes.postDelayed(timeRunnable, 100);
                actionBar.hide();
            }
        }
    }

    protected void playVideo() {
        videoIcon.setVisibility(View.GONE);
        if (mediaPlayer != null) {
            if (mediaPlayer.isPlaying()) {
                mediaPlayer.stop();
            } else {
                if (isSurfaceCreated) {
                    mediaPlayer.setDisplay(surfaceHolder);
                } else {
                    ToastHelper.showToast(WatchVideoActivity.this, R.string.im_look_video_fail_try_again);
                    return;
                }
            }
            mediaPlayer.reset();
            try {
                mediaPlayer.setDataSource(videoFilePath);
            } catch (Exception e) {
                ToastHelper.showToast(WatchVideoActivity.this, R.string.im_look_video_fail_try_again);
                e.printStackTrace();
                return;
            }

            setMediaPlayerListener();
            mediaPlayer.prepareAsync();
            actionBar.hide();
        }
    }

    private void setMediaPlayerListener() {
        mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                videoIcon.setVisibility(View.VISIBLE);

                playState = PLAY_STATE_STOP;
                playTimeTextView.setText("00:00");
                handlerTimes.removeCallbacks(timeRunnable);
                actionBar.show();
            }
        });

        mediaPlayer.setOnErrorListener(new OnErrorListener() {
            @Override
            public boolean onError(MediaPlayer mp, int what, int extra) {
                try {
                    Intent intent = new Intent(Intent.ACTION_VIEW);
                    String type = "video/3gp";
                    Uri name = Uri.parse("file://" + videoFilePath);
                    intent.setDataAndType(name, type);
                    startActivity(intent);
                    finish();
                } catch (Exception e) {
                    ToastHelper.showToastLong(WatchVideoActivity.this, R.string.im_look_video_fail);
                }
                return true;
            }
        });

        mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp)// 缓冲完毕
            {
                mediaPlayer.start();// 播放视频
                initVideoSize();//根据视频宽高，调整视频显示
                // if (position > 0) {
                // mediaPlayer.seekTo(position);
                // mediaPlayer.start();
                // }
                handlerTimes.postDelayed(timeRunnable, 100);
            }
        });
    }

    /**
     * **************************** 下载视频 *********************************
     */
    private void showVideoInfo() {
        long duration = ((VideoAttachment) message.getAttachment()).getDuration();
        long fileSize = ((VideoAttachment) message.getAttachment()).getSize();

        if (duration <= 0) {
            fileInfoTextView.setText("大小: " + FileUtil.formatFileSize(fileSize));
        } else {
            long seconds = TimeUtil.getSecondsByMilliseconds(duration);
            fileInfoTextView.setText("大小: " + FileUtil.formatFileSize(fileSize) + ",时长: "
                    + String.valueOf(seconds) + " 秒");
            videoLength = seconds;
        }
    }

    private void registerObservers(boolean register) {
        NIMClient.getService(MsgServiceObserve.class).observeMsgStatus(statusObserver, register);
        NIMClient.getService(MsgServiceObserve.class).observeAttachmentProgress(attachmentProgressObserver, register);
    }

    private Observer<IMMessage> statusObserver = new Observer<IMMessage>() {
        @Override
        public void onEvent(IMMessage msg) {
            if (!msg.isTheSame(message) || isDestroyedCompatible()) {
                return;
            }

            if (msg.getAttachStatus() == AttachStatusEnum.transferred && isVideoHasDownloaded(msg)) {
                onDownloadSuccess(msg);
            } else if (msg.getAttachStatus() == AttachStatusEnum.fail) {
                onDownloadFailed();
            }
        }
    };

    private Observer<AttachmentProgress> attachmentProgressObserver = new Observer<AttachmentProgress>() {
        @Override
        public void onEvent(AttachmentProgress p) {
            long total = p.getTotal();
            long progress = p.getTransferred();
            float percent = (float) progress / (float) total;
            if (percent > 1.0) {
                // 消息中标识的文件大小有误，小于实际大小
                percent = (float) 1.0;
                progress = total;
            }
            if (percent - lastPercent >= 0.10) {
                lastPercent = percent;
                setDownloadProgress(getString(R.string.im_download_video), progress, total);
            } else {
                if (lastPercent == 0.0) {
                    lastPercent = percent;
                    setDownloadProgress(getString(R.string.im_download_video), progress, total);
                }
                if (percent == 1.0 && lastPercent != 1.0) {
                    lastPercent = percent;
                    setDownloadProgress(getString(R.string.im_download_video), progress, total);
                }
            }
        }
    };

    private void setDownloadProgress(final String label, final long progress, final long total) {
        final float percent = (float) ((double) progress / total);

        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                LayoutParams fgLayoutParams = downloadProgressForeground.getLayoutParams();
                fgLayoutParams.width = (int) (downloadProgressBackground.getWidth() * percent);
                downloadProgressForeground.setLayoutParams(fgLayoutParams);

                downloadProgressText.setText(String.format(getString(R.string.im_download_progress_description), label,
                        FileUtil.formatFileSize(progress), FileUtil.formatFileSize(total)));
            }
        });
    }

    private boolean isVideoHasDownloaded(final IMMessage message) {
        if (message.getAttachStatus() == AttachStatusEnum.transferred &&
                !TextUtils.isEmpty(((VideoAttachment) message.getAttachment()).getPath())) {
            return true;
        }

        return false;
    }

    private void download() {
        if (!isVideoHasDownloaded(message)) {
            // async download original image
            onDownloadStart(message);
            downloadFuture = NIMClient.getService(MsgService.class).downloadAttachment(message, false);
            downloadFuture.setCallback(new RequestCallback<Void>() {
                @Override
                public void onSuccess(Void o) {
                }

                @Override
                public void onFailed(int i) {
                    Apm.INSTANCE.reportCustom("yx_attchment_error", "", new Exception(String.valueOf(i)));
                }

                @Override
                public void onException(Throwable throwable) {
                    Apm.INSTANCE.reportCustom("yx_attchment_error", "", throwable);
                }
            });
            downloading = true;
        }
    }

    private void play() {
        if (isVideoHasDownloaded(message)) {
            onDownloadSuccess(message);
        }
    }

    private void onDownloadSuccess(final IMMessage message) {
        downloadFuture = null;

        downloadLayout.setVisibility(View.GONE);

        videoFilePath = ((VideoAttachment) message.getAttachment()).getPath();

        surfaceView.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                if (playState == PLAY_STATE_PAUSE) {
                    resumeVideo();
                } else if (playState == PLAY_STATE_PLAYING) {
                    pauseVideo();
                } else if (playState == PLAY_STATE_STOP) {
                    playVideo();
                }
            }
        });
        playVideo();
    }

    private void onDownloadFailed() {
        downloadFuture = null;

        downloadLayout.setVisibility(View.GONE);
        ToastHelper.showToast(WatchVideoActivity.this, R.string.im_download_video_fail);
    }

    private void onDownloadStart(IMMessage message) {
        setDownloadProgress(getString(R.string.im_download_video), 0, ((VideoAttachment) message.getAttachment()).getSize());
        downloadLayout.setVisibility(View.VISIBLE);
    }

    private void stopDownload() {
        if (downloadFuture != null) {
            downloadFuture.abort();
            downloadFuture = null;

            downloading = false;
        }
    }

    /**
     * ***************************** SurfaceHolder Callback **************************************
     */
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        if (!isSurfaceCreated) {
            isSurfaceCreated = true;
            play();
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        isSurfaceCreated = false;
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        initVideoSize();// 屏幕旋转后，改变视频显示布局
    }
}
