package com.tencent.liteav.demo.superplayer;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.RelativeLayout;

import com.tencent.liteav.demo.superplayer.player.SuperPlayer;
import com.tencent.liteav.demo.superplayer.player.SuperPlayerImpl;
import com.tencent.liteav.demo.superplayer.player.SuperPlayerObserver;
import com.tencent.liteav.demo.superplayer.ui.player.CastingPlayer;
import com.tencent.liteav.demo.superplayer.ui.player.FullScreenPlayer;
import com.tencent.liteav.demo.superplayer.ui.player.Player;
import com.tencent.liteav.demo.superplayer.ui.player.WindowPlayer;
import com.tencent.liteav.demo.superplayer.util.CastorUtil;
import com.tencent.liteav.demo.superplayer.util.TimeoutUtil;
import com.tencent.rtmp.ui.TXCloudVideoView;

import org.fourthline.cling.model.meta.Device;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;

public class SuperPlayerView extends RelativeLayout implements TimeoutUtil.Listener {
    private static final String TAG = "SuperPlayerView";

    private ViewGroup mRootView;                                 // SuperPlayerView的根view

    private TXCloudVideoView mTXCloudVideoView;                         // 腾讯云视频播放view
    private FullScreenPlayer mFullScreenPlayer;                         // 全屏模式控制view
    private WindowPlayer mWindowPlayer;                                 // 窗口模式控制view
    private CastingPlayer mCastingPlayer;                               // 投屏模式控制view

    private ViewGroup.LayoutParams mLayoutParamWindowMode;              // 窗口播放时SuperPlayerView的布局参数
    private ViewGroup.LayoutParams mLayoutParamFullScreenMode;          // 全屏播放时SuperPlayerView的布局参数

    private LayoutParams mVodControllerWindowParams;      // 窗口controller的布局参数
    private LayoutParams mVodControllerFullScreenParams;  // 全屏controller的布局参数

    private OnPlayerViewCallback mPlayerViewCallback;             // SuperPlayerView回调

    private SuperPlayer mSuperPlayer;                    // 超级播放器

    private int mPlayIndex;                      // 正在播放model的索引
    private SuperPlayerModel mCurrentSuperPlayerModel;        // 当前正在播放的SuperPlayerModel
    private List<SuperPlayerModel> mSuperPlayerModelList;           // SuperPlayerModel列表

    private boolean mIsPlayInit;
    private boolean mIsTimeOut;

    // 正常窗口模式下裁切的圆角值
    private float topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius;

    public SuperPlayerView(Context context) {
        this(context, null);
    }

    public SuperPlayerView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SuperPlayerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context);
        initPlayer(context);
        initAttrs(context, attrs);
        setWillNotDraw(false);
    }

    private void initAttrs(Context context, AttributeSet attrs) {
        if (attrs != null) {
            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundImageView);
            float radius = a.getDimension(R.styleable.RoundImageView_radius, 0f);
            topLeftRadius = a.getDimension(R.styleable.RoundImageView_topLeftRadius, radius);
            topRightRadius = a.getDimension(R.styleable.RoundImageView_topRightRadius, radius);
            bottomLeftRadius = a.getDimension(R.styleable.RoundImageView_bottomLeftRadius, radius);
            bottomRightRadius = a.getDimension(R.styleable.RoundImageView_bottomRightRadius, radius);
            a.recycle();
        }
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        TimeoutUtil.INSTANCE.addListener(this);
    }

    @Override
    protected void onDetachedFromWindow() {
        TimeoutUtil.INSTANCE.removeListener(this);
        super.onDetachedFromWindow();
    }

    /**
     * 初始化view
     */
    private void initView(Context context) {
        mRootView = (ViewGroup) LayoutInflater.from(context).inflate(R.layout.superplayer_vod_view, null);

        mTXCloudVideoView = mRootView.findViewById(R.id.superplayer_cloud_video_view);
        mFullScreenPlayer = mRootView.findViewById(R.id.superplayer_controller_large);
        mWindowPlayer = mRootView.findViewById(R.id.superplayer_controller_small);
        mCastingPlayer = mRootView.findViewById(R.id.superplayer_controller_cast);
        //防止stop中空指针异常
        mSuperPlayerModelList = new ArrayList<>();

        mVodControllerWindowParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        mVodControllerFullScreenParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);

        mFullScreenPlayer.setCallback(mControllerCallback);
        mWindowPlayer.setCallback(mControllerCallback);
        mCastingPlayer.setCallback(mControllerCallback);

        removeAllViews();
        mRootView.removeView(mTXCloudVideoView);
        mRootView.removeView(mCastingPlayer);
        mRootView.removeView(mWindowPlayer);
        mRootView.removeView(mFullScreenPlayer);

        addView(mTXCloudVideoView);
    }

    private void initPlayer(Context context) {
        mSuperPlayer = new SuperPlayerImpl(context, mTXCloudVideoView);
        mSuperPlayer.setObserver(new PlayerObserver());

        if (mSuperPlayer.getPlayerMode() == SuperPlayerDef.PlayerMode.FULLSCREEN) {
            addView(mFullScreenPlayer);
            mCastingPlayer.hide();
            mFullScreenPlayer.hide();
        } else if (mSuperPlayer.getPlayerMode() == SuperPlayerDef.PlayerMode.WINDOW) {
            addView(mWindowPlayer);
            mWindowPlayer.hide();
            mCastingPlayer.hide();
        } else if (mSuperPlayer.getPlayerMode() == SuperPlayerDef.PlayerMode.CASTING) {
            addView(mCastingPlayer);
            mWindowPlayer.hide();
            mFullScreenPlayer.hide();
        }

        post(() -> {
            if (mSuperPlayer.getPlayerMode() == SuperPlayerDef.PlayerMode.WINDOW) {
                mLayoutParamWindowMode = getLayoutParams();
            }
            try {
                // 依据上层Parent的LayoutParam类型来实例化一个新的fullscreen模式下的LayoutParam
                Class parentLayoutParamClazz = getLayoutParams().getClass();
                Constructor constructor = parentLayoutParamClazz.getDeclaredConstructor(int.class, int.class);
                mLayoutParamFullScreenMode = (ViewGroup.LayoutParams) constructor.newInstance(
                        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    public void setupModelList(List<SuperPlayerModel> models) {
        mSuperPlayerModelList = models;
    }

    public void maybePlayIndexModel(int index) {
        int playIndex = (index) % mSuperPlayerModelList.size();
        SuperPlayerModel playModel = mSuperPlayerModelList.get(playIndex);

        mPlayerViewCallback.onPlayPrepare(playIndex, playModel);
    }

    public void playIndexModel(int index) {
        playModelInList(index);
    }

    /* 播放下一个 */
    private void playNextVideo() {
        maybePlayIndexModel(++mPlayIndex);
    }

    /* 播放指定的 */
    private void playModelInList(int index) {
        if (mIsTimeOut) return;
        if ((index >= mSuperPlayerModelList.size())) return;

        mPlayIndex = (index) % mSuperPlayerModelList.size();
        mIsPlayInit = false;
        mSuperPlayer.stop();
        mPlayIndex = index;
        updateNextButton();
        mCurrentSuperPlayerModel = mSuperPlayerModelList.get(mPlayIndex);
        playWithModelInner(mCurrentSuperPlayerModel);
        mIsPlayInit = true;
    }

    private void updateNextButton() {
        if (mPlayIndex < mSuperPlayerModelList.size() - 1) {
            mWindowPlayer.setPlayNextButtonVisibility(true);
            mFullScreenPlayer.setPlayNextButtonVisibility(true);
        } else {
            mWindowPlayer.setPlayNextButtonVisibility(false);
            mFullScreenPlayer.setPlayNextButtonVisibility(false);
        }
    }

    private void playWithModelInner(SuperPlayerModel model) {
        if (mIsTimeOut) return;

        if (mPlayerViewCallback != null) {
            mPlayerViewCallback.onPlayIndex(mPlayIndex, model);
        }

        mSuperPlayer.play(model);
        mFullScreenPlayer.preparePlayVideo(model);
        mWindowPlayer.preparePlayVideo(model);
    }

    /**
     * resume生命周期回调
     */
    public void onResume() {
        if (mSuperPlayer.getPlayerState() == SuperPlayerDef.PlayerState.INIT) {
            return;
        }
        mSuperPlayer.resume();
    }

    /**
     * pause生命周期回调
     */
    public void onPause() {
        if (mSuperPlayer.getPlayerState() == SuperPlayerDef.PlayerState.INIT) {
            return;
        }
        mSuperPlayer.pause();
    }

    /**
     * 重置播放器
     */
    public void resetPlayer() {
        mSuperPlayerModelList.clear();
        stopPlay();
    }

    /**
     * 停止播放
     */
    public void stopPlay() {
        mIsPlayInit = false;
        mSuperPlayer.stop();
    }

    public void startCast(Device device) {
        switchPlayMode(SuperPlayerDef.PlayerMode.CASTING);
        mSuperPlayer.startCast(device);
    }

    public void stopCast() {
        mIsPlayInit = false;
        mSuperPlayer.stopCast();
        switchPlayMode(SuperPlayerDef.PlayerMode.WINDOW);
        mIsPlayInit = true;
        CastorUtil.INSTANCE.selectDevice(null);
    }

    @Override
    public void onTimeout(boolean timeout) {
        this.mIsTimeOut = timeout;
        setNeedToPause(timeout);

        if (timeout) {
            switchPlayMode(SuperPlayerDef.PlayerMode.FULLSCREEN);
        }

        mSuperPlayer.onTimeout(timeout);
        mFullScreenPlayer.onTimeout(timeout);
        mWindowPlayer.onTimeout(timeout);
    }

    /**
     * 设置超级播放器的回调
     *
     * @param callback
     */
    public void setPlayerViewCallback(OnPlayerViewCallback callback) {
        mPlayerViewCallback = callback;
    }

    public void switchPlayMode(SuperPlayerDef.PlayerMode playerMode) {
        if (mControllerCallback != null) {
            mControllerCallback.onSwitchPlayMode(playerMode);
        }
    }

    private void handleSwitchPlayMode(SuperPlayerDef.PlayerMode playerMode) {
        if (playerMode == getPlayerMode()) {
            return;
        }

        mFullScreenPlayer.hide();
        mWindowPlayer.hide();
        mCastingPlayer.hide();

        if (playerMode == SuperPlayerDef.PlayerMode.FULLSCREEN) {
            onSwitchFullMode(playerMode);
        } else if (playerMode == SuperPlayerDef.PlayerMode.WINDOW) {
            onSwitchWindowMode(playerMode);
        } else if (playerMode == SuperPlayerDef.PlayerMode.CASTING) {
            onSwitchCastingMode(playerMode);
        }
    }

    private void onSwitchFullMode(SuperPlayerDef.PlayerMode playerMode) {
        if (mLayoutParamFullScreenMode == null) {
            return;
        }

        removeView(mWindowPlayer);
        removeView(mCastingPlayer);
        addView(mFullScreenPlayer, mVodControllerFullScreenParams);
        setLayoutParams(mLayoutParamFullScreenMode);
        if (mPlayerViewCallback != null) {
            mPlayerViewCallback.onStartFullScreenPlay();
        }

        mSuperPlayer.switchPlayMode(playerMode);
    }

    private void onSwitchWindowMode(SuperPlayerDef.PlayerMode playerMode) {
        if (mLayoutParamWindowMode == null) {
            return;
        }

        removeView(mFullScreenPlayer);
        removeView(mCastingPlayer);
        addView(mWindowPlayer, mVodControllerWindowParams);
        setLayoutParams(mLayoutParamWindowMode);
        if (mPlayerViewCallback != null) {
            mPlayerViewCallback.onStopFullScreenPlay();
        }

        mSuperPlayer.switchPlayMode(playerMode);
    }

    private void onSwitchCastingMode(SuperPlayerDef.PlayerMode playerMode) {
        if (mLayoutParamWindowMode == null) {
            return;
        }

        removeView(mWindowPlayer);
        removeView(mFullScreenPlayer);
        addView(mCastingPlayer, mVodControllerWindowParams);
        setLayoutParams(mLayoutParamWindowMode);
        if (mPlayerViewCallback != null) {
            mPlayerViewCallback.onStopFullScreenPlay();
        }

        mSuperPlayer.switchPlayMode(playerMode);
    }

    /**
     * 初始化controller回调
     */
    private Player.Callback mControllerCallback = new Player.Callback() {
        @Override
        public void onSwitchPlayMode(SuperPlayerDef.PlayerMode playerMode) {
            handleSwitchPlayMode(playerMode);
        }

        @Override
        public void onBackPressed(SuperPlayerDef.PlayerMode playMode) {
            switch (playMode) {
                case FULLSCREEN:// 当前是全屏模式，返回切换成窗口模式
                    onSwitchPlayMode(SuperPlayerDef.PlayerMode.WINDOW);
                    break;
                case WINDOW:// 当前是窗口模式，返回退出播放器
                    break;
                default:
                    break;
            }
        }

        @Override
        public void onPause() {
            mSuperPlayer.pause();
        }

        @Override
        public void onResume() {
            handleResume();
        }

        @Override
        public void verify(SuperPlayerDef.VerifyReason reason) {
            if (mPlayerViewCallback != null) {
                mPlayerViewCallback.onVerify(reason);
            }
        }

        @Override
        public void onSeekTo(int position) {
            mSuperPlayer.seek(position);
        }

        @Override
        public void playNext() {
            playNextVideo();
        }

        @Override
        public void stopCast() {
            SuperPlayerView.this.stopCast();
        }

        @Override
        public List<SuperPlayerModel> getPlayList() {
            if (null == mSuperPlayerModelList || mSuperPlayerModelList.isEmpty()) {
                return new ArrayList<SuperPlayerModel>() {{
                    add(mCurrentSuperPlayerModel);
                }};
            }
            return mSuperPlayerModelList;
        }

        @Override
        public SuperPlayerModel getPlayingVideoModel() {
            return mCurrentSuperPlayerModel;
        }
    };

    public SuperPlayerModel getPlayingVideoModel() {
        return mCurrentSuperPlayerModel;
    }

    private void handleResume() {
        if (mSuperPlayer.getPlayerState() == SuperPlayerDef.PlayerState.LOADING) {
            mSuperPlayer.resume();
        } else if (mSuperPlayer.getPlayerState() == SuperPlayerDef.PlayerState.INIT) {
            mSuperPlayer.resume();
        } else if (mSuperPlayer.getPlayerState() == SuperPlayerDef.PlayerState.END) { //重播
            mSuperPlayer.restart();
        } else if (mSuperPlayer.getPlayerState() == SuperPlayerDef.PlayerState.PAUSE) { //继续播放
            mSuperPlayer.resume();
        }
    }

    /**
     * SuperPlayerView的回调接口
     */
    public interface OnPlayerViewCallback {

        /**
         * 开始全屏播放
         */
        void onStartFullScreenPlay();

        /**
         * 结束全屏播放
         */
        void onStopFullScreenPlay();

        /**
         * 播放下一个视频------
         */
        void onPlayIndex(int index, SuperPlayerModel model);

        /**
         * 检查是否可以播放
         */
        void onPlayPrepare(int index, SuperPlayerModel model);

        /**
         * 弹出验证框
         */
        void onVerify(SuperPlayerDef.VerifyReason reason);
    }

    public void release() {
        if (mWindowPlayer != null) {
            mWindowPlayer.release();
        }
        if (mFullScreenPlayer != null) {
            mFullScreenPlayer.release();
        }
        if (mCastingPlayer != null) {
            mCastingPlayer.release();
        }
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        try {
            release();
        } catch (Throwable e) {
            Log.e(TAG, Log.getStackTraceString(e));
        }
    }


    public SuperPlayerDef.PlayerMode getPlayerMode() {
        return mSuperPlayer.getPlayerMode();
    }

    public SuperPlayerDef.PlayerState getPlayerState() {
        return mSuperPlayer.getPlayerState();
    }


    class PlayerObserver extends SuperPlayerObserver {

        @Override
        public void onPlayPrepare() {
            mWindowPlayer.updatePlayState(SuperPlayerDef.PlayerState.INIT);
            mFullScreenPlayer.updatePlayState(SuperPlayerDef.PlayerState.INIT);
            mCastingPlayer.updatePlayState(SuperPlayerDef.PlayerState.INIT);

            mWindowPlayer.showBackground();
            mFullScreenPlayer.showBackground();
        }

        @Override
        public void onPlayBegin(String name) {
            mWindowPlayer.updatePlayState(SuperPlayerDef.PlayerState.PLAYING);
            mFullScreenPlayer.updatePlayState(SuperPlayerDef.PlayerState.PLAYING);
            mCastingPlayer.updatePlayState(SuperPlayerDef.PlayerState.PLAYING);

            mWindowPlayer.hideBackground();
            mFullScreenPlayer.hideBackground();
        }

        @Override
        public void onPlayPause() {
            mWindowPlayer.updatePlayState(SuperPlayerDef.PlayerState.PAUSE);
            mFullScreenPlayer.updatePlayState(SuperPlayerDef.PlayerState.PAUSE);
            mCastingPlayer.updatePlayState(SuperPlayerDef.PlayerState.PAUSE);
        }

        @Override
        public void onPlayStop() {
            if (mIsPlayInit) {
                playNextVideo();
            }
        }

        @Override
        public void onPlayLoading() {
            mWindowPlayer.updatePlayState(SuperPlayerDef.PlayerState.LOADING);
            mFullScreenPlayer.updatePlayState(SuperPlayerDef.PlayerState.LOADING);
            mCastingPlayer.updatePlayState(SuperPlayerDef.PlayerState.LOADING);
        }

        @Override
        public void onPlayProgress(long current, long duration) {
            mWindowPlayer.updateVideoProgress(current, duration);
            mFullScreenPlayer.updateVideoProgress(current, duration);
            mCastingPlayer.updateVideoProgress(current, duration);
        }

        @Override
        public void onSeek(int position) {

        }

        @Override
        public void onError(int code, String message) {
        }

        @Override
        public void onRcvFirstIframe() {
            super.onRcvFirstIframe();
            mWindowPlayer.toggleCoverView(false);
            mFullScreenPlayer.toggleCoverView(false);
        }
    }

    public void setNeedToPause(boolean value) {
        mSuperPlayer.setNeedToPause(value);
    }

    public void setStartTime(double startTime) {
        mSuperPlayer.setStartTime((float) startTime);
    }

    /*                                                  */
    /*----------------正常窗口播放时裁切圆角----------------*/
    @Override
    public void draw(Canvas canvas) {
        canvas.save();
        canvas.clipPath(getClipPath(getWidth(), getHeight()));
        super.draw(canvas);
        canvas.restore();
    }

    private Path getClipPath(int width, int height) {
        final Path path = new Path();
        float[] radiusArray = new float[]{
                topLeftRadius, topLeftRadius, topRightRadius, topRightRadius,
                bottomRightRadius, bottomRightRadius, bottomLeftRadius, bottomLeftRadius
        };
        path.addRoundRect(new RectF(0, 0, width, height), radiusArray, Path.Direction.CW);

        return path;
    }
}
