package com.yidianling.avchatkit.ui;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.widget.Button;
import android.widget.Chronometer;
import android.widget.TextView;
import com.netease.nimlib.sdk.avchat.AVChatCallback;
import com.netease.nimlib.sdk.avchat.AVChatManager;
import com.netease.nimlib.sdk.avchat.constant.AVChatControlCommand;
import com.netease.nimlib.sdk.avchat.constant.AVChatType;
import com.netease.nimlib.sdk.avchat.model.AVChatData;
import com.tbruyelle.rxpermissions2.Permission;
import com.tbruyelle.rxpermissions2.RxPermissions;
import com.yidianling.avchatkit.AVChatKit;
import com.yidianling.im.R;
import com.yidianling.avchatkit.activity.AVChatActivity;
import com.yidianling.avchatkit.common.imageview.HeadImageView;
import com.yidianling.avchatkit.common.log.LogUtil;
import com.yidianling.avchatkit.common.util.NetworkUtil;
import com.yidianling.avchatkit.common.widgets.ToggleListener;
import com.yidianling.avchatkit.common.widgets.ToggleState;
import com.yidianling.avchatkit.common.widgets.ToggleView;
import com.yidianling.avchatkit.constant.AVChatExitCode;
import com.yidianling.avchatkit.constant.CallStateEnum;
import com.yidianling.avchatkit.controll.AVChatController;
import com.yidianling.avchatkit.module.AVChatControllerCallback;
import com.yidianling.avchatkit.module.AVSwitchListener;
import com.yidianling.common.tools.ToastUtil;
import com.ydl.ydlcommon.utils.DeviceTool;

import io.reactivex.functions.Consumer;

/**
 * 音频界面显示变化以及点击事件
 * Created by winnie on 2017/12/10.
 */

public class AVChatAudioUI implements View.OnClickListener, ToggleListener {
    // constant
    private static final int[] NETWORK_GRADE_DRAWABLE = new int[]{R.drawable.im_network_grade_0, R.drawable.im_network_grade_1, R.drawable.im_network_grade_2, R.drawable.im_network_grade_3};
    private static final int[] NETWORK_GRADE_LABEL = new int[]{R.string.im_avchat_network_grade_0, R.string.im_avchat_network_grade_1, R.string.im_avchat_network_grade_2, R.string.im_avchat_network_grade_3};
    private static final String TAG = AVChatAudioUI.class.getSimpleName();


    private Context context;

    // view
    private View rootView;
    private View switchVideo;
    private HeadImageView headImg;
    private TextView nickNameTV;
    private Chronometer time;
    private TextView wifiUnavailableNotifyTV;
    private TextView notifyTV;
    private TextView netUnstableTV;

    private View mute_speaker_hangup;
    private ToggleView muteToggle;
    private ToggleView speakerToggle;
    private View recordToggle;
    private Button recordToggleButton;
    private View hangup;

    private View refuse_receive;
    private TextView refuseTV;
    private TextView receiveTV;

    private View recordView;
    private View recordTip;
    private View recordWarning;

    // state
    private boolean init = false;
    private boolean isInSwitch = false;
    private boolean isEnabled = false;
    private boolean isRecordWarning = false;

    private String account;
    private String displayName;
    private AVChatController avChatController;
    private AVSwitchListener avSwitchListener;
    private CallStateEnum callingState;

    public AVChatAudioUI(Context context, View root, String displayName,
                         AVChatController avChatController, AVSwitchListener avSwitchListener) {
        this.context = context;
        this.rootView = root;
        this.displayName = displayName;
        this.avChatController = avChatController;
        this.avSwitchListener = avSwitchListener;
    }

    private void findViews() {
        if (init || rootView == null) {
            return;
        }
        switchVideo = rootView.findViewById(R.id.avchat_audio_switch_video);
        switchVideo.setOnClickListener(this);

        headImg = rootView.findViewById(R.id.avchat_audio_head);
        nickNameTV = rootView.findViewById(R.id.avchat_audio_nickname);
        time = rootView.findViewById(R.id.avchat_audio_time);
        wifiUnavailableNotifyTV = rootView.findViewById(R.id.avchat_audio_wifi_unavailable);
        notifyTV = rootView.findViewById(R.id.avchat_audio_notify);
        netUnstableTV = rootView.findViewById(R.id.avchat_audio_netunstable);

        mute_speaker_hangup = rootView.findViewById(R.id.avchat_audio_mute_speaker_huangup);
        View mute = mute_speaker_hangup.findViewById(R.id.avchat_audio_mute);
        muteToggle = new ToggleView(mute, ToggleState.OFF, this);
        View speaker = mute_speaker_hangup.findViewById(R.id.avchat_audio_speaker);
        speakerToggle = new ToggleView(speaker, ToggleState.OFF, this);
        recordToggle = mute_speaker_hangup.findViewById(R.id.avchat_audio_record);
        recordToggleButton = mute_speaker_hangup.findViewById(R.id.avchat_audio_record_button);

        hangup = mute_speaker_hangup.findViewById(R.id.avchat_audio_hangup);
        hangup.setOnClickListener(this);
        recordToggle.setOnClickListener(this);
        recordToggle.setEnabled(false);

        refuse_receive = rootView.findViewById(R.id.avchat_audio_refuse_receive);
        refuseTV = refuse_receive.findViewById(R.id.refuse);
        receiveTV = refuse_receive.findViewById(R.id.receive);
        refuseTV.setOnClickListener(this);
        receiveTV.setOnClickListener(this);

        recordView = rootView.findViewById(R.id.avchat_record_layout);
        recordTip = rootView.findViewById(R.id.avchat_record_tip);
        recordWarning = rootView.findViewById(R.id.avchat_record_warning);

        init = true;
    }

    public void onDestroy() {
        if (time != null) {
            time.stop();
        }
    }

    /**
     * ************************ 音频主流程事件 ************************
     */

    public void showIncomingCall(AVChatData avChatData) {
        // 接听方的数据是AVChatData
        this.account = avChatData.getAccount();
        this.callingState = CallStateEnum.INCOMING_AUDIO_CALLING;

        findViews();

        setSwitchVideo(false);
        showProfile();//对方的详细信息
        showNotify(R.string.im_avchat_audio_call_request);
        setMuteSpeakerHangupControl(false);
        setRefuseReceive(true);
        receiveTV.setText(R.string.im_avchat_pickup);
    }

    public void showAudioInitLayout() {
        findViews();

        isInSwitch = false;
        setWifiUnavailableNotifyTV(false);
        showNetworkCondition(1);
        showProfile();
        setSwitchVideo(true);
        setTime(true);
        hideNotify();
        setMuteSpeakerHangupControl(true);
        setRefuseReceive(false);
        enableToggle();
    }

    public void doOutGoingCall(String account) {
        // 拨打方的数据是account
        this.account = account;
        findViews();

        setSwitchVideo(false);
        showProfile();//对方的详细信息
        showNotify(R.string.im_avchat_wait_recieve);
        setWifiUnavailableNotifyTV(true);
        setMuteSpeakerHangupControl(true);
        setRefuseReceive(false);

        // 拨打音视频接口调用
        avChatController.doCalling(account, AVChatType.AUDIO, new AVChatControllerCallback<AVChatData>() {
            @Override
            public void onSuccess(AVChatData avChatData) {
                avChatController.setAvChatData(avChatData);
            }

            @Override
            public void onFailed(int code, String errorMsg) {
                closeSession();
            }
        });
    }

    /**
     * ********************* 音视频切换 **********************
     */

    // 视频切换为音频时，禁音与扬声器按钮状态
    public void onVideoToAudio(boolean muteOn, boolean speakerOn, String account) {

        this.account = account;
        showAudioInitLayout();

        muteToggle.toggle(muteOn ? ToggleState.ON : ToggleState.OFF);
        speakerToggle.toggle(speakerOn ? ToggleState.ON : ToggleState.OFF);
        recordToggle.setSelected(avChatController.isRecording());

        showRecordView(avChatController.isRecording(), isRecordWarning);
    }

    public void showIncomingAudioToVideo() {
        callingState = CallStateEnum.INCOMING_AUDIO_TO_VIDEO;

        setSwitchVideo(false);
        showProfile();//对方的详细信息
        showNotify(R.string.im_avchat_audio_call_request);
        setMuteSpeakerHangupControl(false);
        setRefuseReceive(true);
        receiveTV.setText(R.string.im_avchat_pickup);
    }


    /**
     * *************** 界面变化 *****************
     */

    // 显示或隐藏音视频切换
    private void setSwitchVideo(boolean visible) {
        switchVideo.setVisibility(visible ? View.VISIBLE : View.GONE);
    }

    // 界面状态文案设置
    private void showNotify(int resId) {
        notifyTV.setText(resId);
        notifyTV.setVisibility(View.VISIBLE);
    }

    //
    private void showProfile() {
        headImg.loadBuddyAvatar(avChatController.getAvChatData() == null ? account
                : avChatController.getAvChatData().getAccount());
        nickNameTV.setText(displayName);
    }

    // 显示或隐藏禁音，结束通话布局
    private void setMuteSpeakerHangupControl(boolean visible) {
        mute_speaker_hangup.setVisibility(visible ? View.VISIBLE : View.GONE);
    }

    // 显示或隐藏拒绝，开启布局
    private void setRefuseReceive(boolean visible) {
        refuse_receive.setVisibility(visible ? View.VISIBLE : View.GONE);
    }

    // 显示或者隐藏是否为wifi的提示
    private void setWifiUnavailableNotifyTV(boolean show) {
        if (show && !NetworkUtil.isWifi(AVChatKit.getContext())) {
            wifiUnavailableNotifyTV.setVisibility(View.VISIBLE);
        } else {
            wifiUnavailableNotifyTV.setVisibility(View.GONE);
        }
    }

    // 显示网络状态
    public void showNetworkCondition(int grade) {
        if (grade >= 0 && grade < NETWORK_GRADE_DRAWABLE.length) {
            netUnstableTV.setText(NETWORK_GRADE_LABEL[grade]);
            Drawable drawable = AVChatKit.getContext().getResources().getDrawable(NETWORK_GRADE_DRAWABLE[grade]);
            if (drawable != null) {
                drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
                netUnstableTV.setCompoundDrawables(null, null, drawable, null);
            }
            netUnstableTV.setVisibility(View.VISIBLE);
        }
    }

    // 设置通话时间显示
    private void setTime(boolean visible) {
        time.setVisibility(visible ? View.VISIBLE : View.GONE);
        if (visible) {
            time.setBase(avChatController.getTimeBase());
            time.start();
        }
    }

    // 隐藏界面文案
    private void hideNotify() {
        notifyTV.setVisibility(View.GONE);
    }

    private void enableToggle() {
        if (!isEnabled) {
            recordToggle.setEnabled(true);
        }
        isEnabled = true;
    }

    /**
     * ************************ 点击事件 **************************
     */

    @Override
    public void toggleOn(View v) {
        onClick(v);
    }

    @Override
    public void toggleOff(View v) {
        onClick(v);
    }

    @Override
    public void toggleDisable(View v) {

    }

    @Override
    public void onClick(View v) {
        int i = v.getId();
        if (i == R.id.refuse) {
            doRefuseCall();
        } else if (i == R.id.receive) {
            requestPermission();
        } else if (i == R.id.avchat_audio_hangup) {
            doHangUp();
        } else if (i == R.id.avchat_audio_mute) {
            avChatController.toggleMute();
        } else if (i == R.id.avchat_audio_speaker) {
            avChatController.toggleSpeaker();
        } else if (i == R.id.avchat_audio_record) {
            doRecording();
        } else if (i == R.id.avchat_audio_switch_video) {
            if (isInSwitch) {
                ToastUtil.toastShort(context, R.string.im_avchat_in_switch);
            } else {
                avChatController.switchAudioToVideo(avSwitchListener);
            }
        }
    }

    // 拒绝来电
    private void doRefuseCall() {
        if (callingState == CallStateEnum.INCOMING_AUDIO_CALLING) {
            avChatController.hangUp(AVChatExitCode.HANGUP);
            closeSession();
        } else if (callingState == CallStateEnum.INCOMING_AUDIO_TO_VIDEO) {
            rejectAudioToVideo();
        }
    }

    // 拒绝音视频切换
    private void rejectAudioToVideo() {
        AVChatManager.getInstance().sendControlCommand(avChatController.getAvChatData().getChatId(), AVChatControlCommand.SWITCH_AUDIO_TO_VIDEO_REJECT, new AVChatCallback<Void>() {
            @Override
            public void onSuccess(Void aVoid) {
                LogUtil.i(TAG, "rejectAudioToVideo success");
                showAudioInitLayout();
            }

            @Override
            public void onFailed(int code) {
                LogUtil.i(TAG, "rejectAudioToVideo onFailed");

            }

            @Override
            public void onException(Throwable exception) {
                LogUtil.i(TAG, "rejectAudioToVideo onException");
            }
        });
    }

    private void requestPermission() {
        new RxPermissions((Activity) this.context)
                .requestEach(Manifest.permission.RECORD_AUDIO,Manifest.permission.CAMERA)
                .subscribe(new Consumer<Permission>() {
                    @Override
                    public void accept(Permission permission) throws Exception {
                        if (permission.granted) {
                            doReceiveCall();
                        } else if (permission.shouldShowRequestPermissionRationale){
                            requestPermission();
                        }else {
                            ToastUtil.toastLong(context,"请开启相机和麦克风权限后重试");
                            DeviceTool.openPersisonSetting((Activity) AVChatAudioUI.this.context);
                            ((Activity) AVChatAudioUI.this.context).finish();
                        }
                    }
                } );
    }

    // 接听来电
    private void doReceiveCall() {
        if (callingState == CallStateEnum.INCOMING_AUDIO_CALLING) {
            showNotify(R.string.im_avchat_connecting);

            avChatController.receive(AVChatType.AUDIO, new AVChatControllerCallback<Void>() {
                @Override
                public void onSuccess(Void aVoid) {

                }

                @Override
                public void onFailed(int code, String errorMsg) {
                    closeSession();
                }
            });
        } else if (callingState == CallStateEnum.INCOMING_AUDIO_TO_VIDEO) {
            avChatController.receiveAudioToVideo(avSwitchListener);
        }

    }

    // 通话过程中，挂断电话
    private void doHangUp() {
        avChatController.hangUp(AVChatExitCode.HANGUP);
        closeSession();
    }

    private void doRecording() {
        avChatController.toggleRecord(AVChatType.AUDIO.getValue(), account, new AVChatController.RecordCallback() {
            @Override
            public void onRecordUpdate(boolean isRecording) {
                showRecordView(isRecording, isRecordWarning);
            }
        });
    }

    public void showRecordView(boolean show, boolean warning) {
        if (show) {
            recordToggle.setSelected(true);
            recordToggleButton.setText("结束");
            recordView.setVisibility(View.VISIBLE);
            recordTip.setVisibility(View.VISIBLE);
            if (warning) {
                recordWarning.setVisibility(View.VISIBLE);
            } else {
                recordWarning.setVisibility(View.GONE);
            }
        } else {
            recordToggle.setSelected(false);
            recordToggleButton.setText("录制");
            recordView.setVisibility(View.INVISIBLE);
            recordTip.setVisibility(View.INVISIBLE);
            recordWarning.setVisibility(View.GONE);
        }
    }

    public void showRecordWarning() {
        isRecordWarning = true;
        showRecordView(avChatController.isRecording(), isRecordWarning);
    }

    public void resetRecordTip() {
        isRecordWarning = false;
        avChatController.setRecording(false);
        showRecordView(false, isRecordWarning);
    }


    private void closeSession() {
        ((AVChatActivity) context).finish();
    }
}
