package com.bokecc.livemodule.view;

import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.media.AudioManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;

import com.bokecc.projection.ProjectionBrowseRegistryListener;
import com.bokecc.projection.ProjectionControlCallback;
import com.bokecc.projection.ProjectionControlReceiveCallback;
import com.bokecc.projection.ProjectionDLANPlayState;
import com.bokecc.projection.ProjectionDevice;
import com.bokecc.projection.ProjectionDeviceListChangedListener;
import com.bokecc.projection.ProjectionDeviceManager;
import com.bokecc.projection.ProjectionIDevice;
import com.bokecc.projection.ProjectionIResponse;
import com.bokecc.projection.ProjectionIntents;
import com.bokecc.projection.ProjectionManager;
import com.bokecc.projection.ProjectionPlayControl;
import com.bokecc.projection.ProjectionPositionResponse;
import com.bokecc.projection.ProjectionUpnpService;
import com.bokecc.projection.ProjectionUtils;
import com.bokecc.projection.ProjectionVolumeResponse;

import org.fourthline.cling.support.model.PositionInfo;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;


public class DLNAController {

    private static final String TAG = "DLNAController";

    private Context mContext;
    private boolean isBindService = false;
    private String playUrl;


    //投屏控制
    private final ProjectionPlayControl projectionPlayControl = new ProjectionPlayControl();
    private BroadcastReceiver mTransportStateBroadcastReceiver;


    //监听发现投屏设备
    private final ProjectionBrowseRegistryListener registryListener = new ProjectionBrowseRegistryListener();

    private boolean isProjecting = false;
    private boolean isProjectingPause = false;
    private boolean isPlaying = false;
    private Timer projectionTimer, searchDeviceTimer;
    private ProjectionTask projectionTask;
    private SearchDeviceTask searchDeviceTask;
    private int SEARCH_DEVICE_TIME = 30;
    private List<ProjectionDevice> datas = new ArrayList<>();
    private DlnaEventListener dlnaEventListener;
    private boolean isProjectionContinue = true, isGetProjectionVolume = true;
    private Integer volumeValue = 0;


    private Handler handler = new Handler(Looper.myLooper());


    public DLNAController(Context mContext, DlnaEventListener listener) {
        this.mContext = mContext;
        this.dlnaEventListener = listener;

        registryListener.setOnDeviceListChangedListener(new ProjectionDeviceListChangedListener() {
            @Override
            public void onDeviceAdded(final ProjectionIDevice device) {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        datas.add((ProjectionDevice) device);
                        if (dlnaEventListener != null) {
                            dlnaEventListener.onDeviceAdded((ProjectionDevice) device);
                        }
//                        deviceAdapter.notifyDataSetChanged();
                    }
                });
            }

            @Override
            public void onDeviceRemoved(final ProjectionIDevice device) {
                handler.post(new Runnable() {
                    public void run() {
                        datas.remove(device);
                        if (dlnaEventListener != null) {
                            dlnaEventListener.onDeviceRemoved((ProjectionDevice) device);
                        }
//                        deviceAdapter.notifyDataSetChanged();
                    }
                });
            }
        });
    }

    /**
     * 投屏准备
     */
    public void prepare() {
        Log.i(TAG, "prepare: ");
        bindService();
        registerReceivers();
    }

    /**
     * 搜索设备
     */
    public void searchDevice() {
        SEARCH_DEVICE_TIME = 30;
        startSearchDeviceTimer();
    }

    /**
     * 搜索设备
     */
    public void stopSearch() {
        cancelSearchDeviceTimer();
    }

    public void selectDevice(ProjectionDevice device) {
        ProjectionManager.getInstance().setSelectedDevice(device);
        if (ProjectionUtils.isNull(device.getDevice())) {
            return;
        }
//        ll_select_projection_device.setVisibility(View.GONE);
        cancelSearchDeviceTimer();
    }

    /**
     * 播放投屏
     */
    public void play(String url) {
        this.playUrl = url;
        Log.i(TAG, "play: " + url);
        playProjection();
    }


    /**
     * 播放投屏
     */
    public void resume() {
        Log.i(TAG, "resume: ");
        playProjection();
    }


    /**
     * 暂停
     */
    public void pause() {
        Log.i(TAG, "pause: ");
        pauseProjection();
    }

    /**
     * 停止投屏
     */
    public void stop() {
        Log.i(TAG, "stop: ");
        stopProjection();
    }

    /**
     * 设置音量加减
     *
     * @param add
     */
    public void setVolume(boolean add) {
        Log.i(TAG, "setVolume: " + (add ? "add" : "sub"));
        changeProjectionVolume(add);
    }

    public void seek(long position) {
        if (isProjecting) {
            projectionPlayControl.seek((int) position, new ProjectionControlCallback() {
                @Override
                public void success(ProjectionIResponse response) {
                    if (dlnaEventListener != null) {
                        dlnaEventListener.onSeeked(true);
                    }
                }

                @Override
                public void fail(ProjectionIResponse response) {
                    if (dlnaEventListener != null) {
                        dlnaEventListener.onSeeked(false);
                    }
                }
            });
        }
    }


    public void destroy() {
        Log.i(TAG, "destroy: ");
        if (isProjecting) {
            stop();
        }
        handler.removeCallbacksAndMessages(null);
        isBindService = false;
        if (mTransportStateBroadcastReceiver != null) {
            mContext.unregisterReceiver(mTransportStateBroadcastReceiver);
        }
        mContext.unbindService(serviceConnection);
    }


    public boolean isProjecting() {
        return isProjecting;
    }

    public boolean isProjectingPaused() {
        return isProjectingPause;
    }


    private void bindService() {
        Intent serviceIntent = new Intent(
                mContext, ProjectionUpnpService.class);
        mContext.bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
        isBindService = true;
    }

    private final ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            Log.i(TAG, "onServiceConnected: ");
            if (dlnaEventListener != null) {
                dlnaEventListener.onServiceConnect();
            }
            try{
                ProjectionUpnpService.LocalBinder binder = (ProjectionUpnpService.LocalBinder) service;
                ProjectionUpnpService projectionUpnpService = binder.getService();

                ProjectionManager projectionManager = ProjectionManager.getInstance();
                projectionManager.setUpnpService(projectionUpnpService);
                projectionManager.setDeviceManager(new ProjectionDeviceManager());
                projectionManager.getRegistry().addListener(registryListener);
                projectionManager.searchDevices();
            }catch (Exception e){
                 e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName className) {
            Log.i(TAG, "onServiceDisconnected: ");
            if (dlnaEventListener != null) {
                dlnaEventListener.onServiceDisConnect();
            }
            ProjectionManager.getInstance().setUpnpService(null);
        }
    };


    /**
     * 接收状态信息
     */
    private class TransportStateBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            Log.i(TAG, "onReceive: ");
            String action = intent.getAction();
            Log.i(TAG, "onReceive: action:" + action);

            if (ProjectionIntents.ACTION_PLAYING.equals(action)) {
                //电视端开始播放
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        //如果收到playing事件，并且，接下来收到的progress的max是0，则判断投屏断开，走断开逻辑
                        isPlaying = true;
                        playingTime = System.currentTimeMillis();
                        if (dlnaEventListener != null) {
                            dlnaEventListener.onPlay(true);
                        }
                    }
                });

            } else if (ProjectionIntents.ACTION_PAUSED_PLAYBACK.equals(action)) {
                //电视端暂停播放
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        isPlaying = false;
                        if (dlnaEventListener != null) {
                            dlnaEventListener.onPause(true);
                        }
                    }
                });

            } else if (ProjectionIntents.ACTION_STOPPED.equals(action)) {
                //电视主动停止播放会触发，手机主动断开不触发此回调
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        isPlaying = false;
                        playingTime = 0L;
                        projectionIsOver();
                        if (dlnaEventListener != null) {
                            dlnaEventListener.onStop(true);
                        }
                    }
                });
            } else if (ProjectionIntents.ACTION_SET_VOLUME.equals(action)) {
                Log.i(TAG, "onReceive: ACTION_SET_VOLUME");
            }
        }
    }

    private void registerReceivers() {
        Log.i(TAG, "registerReceivers: ");
        mTransportStateBroadcastReceiver = new TransportStateBroadcastReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(ProjectionIntents.ACTION_PLAYING);
        filter.addAction(ProjectionIntents.ACTION_PAUSED_PLAYBACK);
        filter.addAction(ProjectionIntents.ACTION_STOPPED);
        filter.addAction(ProjectionIntents.ACTION_TRANSITIONING);
        filter.addAction(ProjectionIntents.ACTION_CHANGE_DEVICE);
        filter.addAction(ProjectionIntents.ACTION_PLAY_COMPLETE);
        filter.addAction(ProjectionIntents.ACTION_UPDATE_LAST_CHANGE);
        mContext.registerReceiver(mTransportStateBroadcastReceiver, filter);
    }

    //播放投屏视频
    private void playProjection() {
        Log.i(TAG, "playProjection: ");
        @ProjectionDLANPlayState.DLANPlayStates
        int currentState = projectionPlayControl.getCurrentState();
        //通过判断状态 来决定 是继续播放 还是重新播放
        if (currentState == ProjectionDLANPlayState.STOP) {
            projectionPlayControl.playNew(playUrl, new ProjectionControlCallback() {
                @Override
                public void success(ProjectionIResponse response) {
                    Log.i(TAG, "playProjection:success: currentState == ProjectionDLANPlayState.STOP");
                    isProjecting = true;
                    isProjectingPause = false;
                    projectionPlayControl.setCurrentState(ProjectionDLANPlayState.PLAY);
                    ProjectionManager.getInstance().registerAVTransport(mContext);
                    ProjectionManager.getInstance().registerRenderingControl(mContext);
                    startProjectionTimer();
                    if (dlnaEventListener != null) {
                        dlnaEventListener.onStartPlay(true);
                    }
                }

                @Override
                public void fail(ProjectionIResponse response) {
                    Log.i(TAG, "playProjection:fail: currentState == ProjectionDLANPlayState.STOP");
                    if (dlnaEventListener != null) {
                        dlnaEventListener.onStartPlay(false);
                    }
                    if (dlnaEventListener != null) {
                        dlnaEventListener.onPlay(false);
                    }
                }
            });
        } else {
            projectionPlayControl.play(new ProjectionControlCallback() {
                @Override
                public void success(ProjectionIResponse response) {
                    Log.i(TAG, "playProjection:success: currentState != ProjectionDLANPlayState.STOP");
                    isProjectingPause = false;
                    isProjecting = true;
                    projectionPlayControl.setCurrentState(ProjectionDLANPlayState.PLAY);
                    if (dlnaEventListener != null) {
                        dlnaEventListener.onStartPlay(true);
                    }
                }

                @Override
                public void fail(ProjectionIResponse response) {
                    Log.i(TAG, "playProjection:fail: currentState != ProjectionDLANPlayState.STOP");
                    if (dlnaEventListener != null) {
                        dlnaEventListener.onPlay(false);
                    }
                    if (dlnaEventListener != null) {
                        dlnaEventListener.onPlay(false);
                    }
                }
            });
        }
    }

    //暂停投屏
    private void pauseProjection() {
        projectionPlayControl.pause(new ProjectionControlCallback() {
            @Override
            public void success(ProjectionIResponse response) {
                Log.i(TAG, "pauseProjection:success: ");
                isProjectingPause = true;
//                iv_play_pause.setImageResource(R.mipmap.iv_play);
                projectionPlayControl.setCurrentState(ProjectionDLANPlayState.PAUSE);
                if (dlnaEventListener != null) {
                    dlnaEventListener.onPause(true);
                }
            }

            @Override
            public void fail(ProjectionIResponse response) {
                Log.i(TAG, "pauseProjection:fail: ");
                if (dlnaEventListener != null) {
                    dlnaEventListener.onPause(false);
                }
            }
        });
    }

    //停止投屏
    private void stopProjection() {
        projectionPlayControl.stop(new ProjectionControlCallback() {
            @Override
            public void success(ProjectionIResponse response) {
                Log.i(TAG, "stopProjection:success: ");
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        if (dlnaEventListener != null) {
                            dlnaEventListener.onStop(true);
                        }
                        projectionIsOver();
                    }
                });
            }

            @Override
            public void fail(ProjectionIResponse response) {
                Log.i(TAG, "stopProjection:fail: ");
                if (dlnaEventListener != null) {
                    dlnaEventListener.onStop(false);
                }
            }
        });
    }

    private void projectionIsOver() {
        Log.i(TAG, "projectionIsOver: ");
        projectionPlayControl.setCurrentState(ProjectionDLANPlayState.STOP);
        isPlaying = false;
        isProjecting = false;
        playingTime = 0L;
        getMaxIsInvalid = false;
        getMaxIsInvalidTime = 0L;
//        rl_projectioning.setVisibility(View.GONE);
//        iv_play_pause.setImageResource(R.mipmap.iv_play);
        cancelProjectionTimer();
    }

    //调整投屏音量
    private void changeProjectionVolume(final boolean isPlus) {
        AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
        int volumeSys = 0;
        if (audioManager!=null){
            volumeSys = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC) * 100 / audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        }
        final int volumeSysFinal = volumeSys;
        projectionPlayControl.setVolume(volumeSysFinal, new ProjectionControlCallback() {
            @Override
            public void success(ProjectionIResponse response) {
                if (dlnaEventListener != null) {
                    dlnaEventListener.onChangeVolume(true, volumeValue);
                }
            }

            @Override
            public void fail(ProjectionIResponse response) {
                if (dlnaEventListener != null) {
                    dlnaEventListener.onChangeVolume(false, volumeValue);
                }
            }
        });
//        projectionPlayControl.getVolume(new ProjectionControlReceiveCallback() {
//            @Override
//            public void receive(ProjectionIResponse response) {
//                if (isGetProjectionVolume) {
//                    ProjectionVolumeResponse projectionVolumeResponse = (ProjectionVolumeResponse) response;
//                    volumeValue = projectionVolumeResponse.getResponse();
//                    isGetProjectionVolume = false;
//                }
//                Log.i(TAG, "changeProjectionVolume:receive: " + volumeValue + "," + (isPlus ? "+" : "-"));
//
//                if (volumeSysFinal!=0){
//                    volumeValue = volumeSysFinal;
//                }else {
//                    if (isPlus) {
//                        volumeValue = volumeValue + 2;
//                    } else {
//                        volumeValue = volumeValue - 2;
//                    }
//                    if (volumeValue < 0) {
//                        volumeValue = 0;
//                    }
//                }
//
//                projectionPlayControl.setVolume(volumeValue, new ProjectionControlCallback() {
//                    @Override
//                    public void success(ProjectionIResponse response) {
//                        if (dlnaEventListener != null) {
//                            dlnaEventListener.onChangeVolume(true, volumeValue);
//                        }
//                    }
//
//                    @Override
//                    public void fail(ProjectionIResponse response) {
//                        if (dlnaEventListener != null) {
//                            dlnaEventListener.onChangeVolume(false, volumeValue);
//                        }
//                    }
//                });
//            }
//
//            @Override
//            public void success(ProjectionIResponse response) {
//                Log.i(TAG, "changeProjectionVolume:success: ");
//            }
//
//            @Override
//            public void fail(ProjectionIResponse response) {
//                Log.i(TAG, "changeProjectionVolume:fail: ");
//            }
//        });
    }


    private void startProjectionTimer() {
        Log.i(TAG, "startProjectionTimer: ");
//        cancelVideoTimer();
        cancelProjectionTimer();
        projectionTimer = new Timer();
        projectionTask = new ProjectionTask();
        projectionTimer.schedule(projectionTask, 0, 1000);
    }

    private void cancelProjectionTimer() {
        Log.i(TAG, "cancelProjectionTimer: ");
        if (projectionTimer != null) {
            projectionTimer.cancel();
        }
        if (projectionTask != null) {
            projectionTask.cancel();
        }
    }


    private long playingTime = 0;
    //获取到的max为0
    private boolean getMaxIsInvalid = false;
    private long getMaxIsInvalidTime = 0L;

    //投屏进度计时器
    class ProjectionTask extends TimerTask {

        @Override
        public void run() {
            projectionPlayControl.getPositionInfo(new ProjectionControlReceiveCallback() {
                @Override
                public void receive(ProjectionIResponse response) {
                    Log.i(TAG, "ProjectionTask:getPositionInfo:receive: ");
                    ProjectionPositionResponse projectionPositionResponse = (ProjectionPositionResponse) response;
                    PositionInfo positionInfo = projectionPositionResponse.getResponse();
                    final long trackDurationSeconds = positionInfo.getTrackDurationSeconds();
                    final long trackElapsedSeconds = positionInfo.getTrackElapsedSeconds();
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            if (isPlaying&&!isLive) {
                                if (System.currentTimeMillis() - playingTime > 3000 && trackDurationSeconds == 0) {
                                    //说明投屏断开，走断开逻辑
                                    stopProjection();
                                }
                            }
                            //当持续5s收到trackDurationSeconds为0时，走断开逻辑
                            if (!isLive){
                                if (!getMaxIsInvalid && trackDurationSeconds == 0) {
                                    getMaxIsInvalid = true;
                                    getMaxIsInvalidTime = System.currentTimeMillis();
                                } else if (getMaxIsInvalid && trackDurationSeconds == 0) {
                                    if (getMaxIsInvalidTime!=0L && System.currentTimeMillis() - getMaxIsInvalidTime > 10000) {
                                        getMaxIsInvalid = false;
                                        getMaxIsInvalidTime = 0L;
                                        stopProjection();
                                    }
                                } else {
                                    getMaxIsInvalid = false;
                                    getMaxIsInvalidTime = 0L;
                                }
                                if (dlnaEventListener != null) {
                                    dlnaEventListener.onProgress(trackElapsedSeconds, trackDurationSeconds);
                                }
                            }


//                            if (trackDurationSeconds > 0) {
//                                tv_current_time.setText(MultiUtils.millsecondsToMinuteSecondStr((trackElapsedSeconds * 1000)));
//                                sb_progress.setProgress((int) trackElapsedSeconds, (int) trackDurationSeconds);
//                                if (trackElapsedSeconds >= (trackDurationSeconds - 2)) {
//                                    mHandler.sendEmptyMessage(STOP_ACTION);
//                                }

//                            }
                        }
                    });
                }

                @Override
                public void success(ProjectionIResponse response) {
                    Log.i(TAG, "getPositionInfo:success");
                }

                @Override
                public void fail(ProjectionIResponse response) {
                    Log.i(TAG, "getPositionInfo:fail");
                }
            });


        }
    }

    //开启搜寻投屏设备任务
    private void startSearchDeviceTimer() {
        cancelSearchDeviceTimer();
        searchDeviceTimer = new Timer();
        searchDeviceTask = new SearchDeviceTask();
        searchDeviceTimer.schedule(searchDeviceTask, 0, 1000);
    }

    //取消搜寻投屏设备任务
    private void cancelSearchDeviceTimer() {
        if (searchDeviceTimer != null) {
            searchDeviceTimer.cancel();
        }
        if (searchDeviceTask != null) {
            searchDeviceTask.cancel();
        }
    }

    private boolean isLive = false;

    public void setIsLive(boolean isLive){
        this.isLive = isLive;
    }
    //搜寻投屏设备计时器
    class SearchDeviceTask extends TimerTask {
        @Override
        public void run() {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    Log.i(TAG, "SearchDeviceTask:run: " + SEARCH_DEVICE_TIME);
                    SEARCH_DEVICE_TIME--;
                    if (SEARCH_DEVICE_TIME == 0) {
                        cancelSearchDeviceTimer();
                        if (datas.isEmpty()) {
                            if (dlnaEventListener != null) {
                                dlnaEventListener.onSearchEnd(true);
                            }
                        } else {
                            if (dlnaEventListener != null) {
                                dlnaEventListener.onSearchEnd(false);
                            }
                        }
                    }
                }
            });
        }
    }


    public interface DlnaEventListener {
        /**
         * 连接成功
         */
        void onServiceConnect();

        /**
         * 断开连接
         */
        void onServiceDisConnect();

        /**
         * 播放回调
         *
         * @param success
         */
        void onPlay(boolean success);

        /**
         * 暂停回调
         *
         * @param success
         */
        void onPause(boolean success);

        /**
         * 停止回调
         *
         * @param success
         */
        void onStop(boolean success);

        /**
         * 进度回调 单位s
         *
         * @param progress
         */
        void onProgress(long progress, long max);

        /**
         * 音量回调
         *
         * @param success
         * @param volume
         */
        void onChangeVolume(boolean success, int volume);

        void onSeeked(boolean success);

        void onDeviceAdded(ProjectionDevice device);

        void onDeviceRemoved(ProjectionDevice device);

        void onSearchEnd(boolean empty);

        void onStartPlay(boolean success);
    }
}
