package com.cygnusa.hyperm.training.activities;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.bumptech.glide.Glide;
import com.github.siyamed.shapeimageview.CircularImageView;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import com.cygnusa.hyperm.R;
import com.cygnusa.hyperm.adapter.AttendanceAdapter;
import com.cygnusa.hyperm.training.chat.Chat;
import com.cygnusa.hyperm.training.chat.ChatManager;
import com.cygnusa.hyperm.training.chat.MessageAdapter;
import com.cygnusa.hyperm.training.stats.LocalStatsData;
import com.cygnusa.hyperm.training.stats.RemoteStatsData;
import com.cygnusa.hyperm.training.stats.StatsData;
import com.cygnusa.hyperm.training.ui.VideoGridContainer;
import com.cygnusa.hyperm.util.ApiService;
import com.cygnusa.hyperm.util.GlobalData;
import com.cygnusa.hyperm.util.MainApplication;
import com.cygnusa.hyperm.util.MyCallback;
import com.cygnusa.hyperm.util.OnSwipeTouchListener;
import com.cygnusa.hyperm.util.TimerTextView;
import com.cygnusa.hyperm.util.TransparentProgressDialog;
import com.cygnusa.hyperm.util.UtilService;
import com.cygnusa.hyperm.wrappers.ActiveResponse;
import com.cygnusa.hyperm.wrappers.ChatResponse;
import com.cygnusa.hyperm.wrappers.CommonResponse;
import com.cygnusa.hyperm.wrappers.DSE;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import io.agora.rtc.Constants;
import io.agora.rtc.IRtcEngineEventHandler;
import io.agora.rtc.video.VideoEncoderConfiguration;
import io.agora.rtm.ErrorInfo;
import io.agora.rtm.ResultCallback;
import io.agora.rtm.RtmChannel;
import io.agora.rtm.RtmChannelAttribute;
import io.agora.rtm.RtmChannelListener;
import io.agora.rtm.RtmChannelMember;
import io.agora.rtm.RtmClient;
import io.agora.rtm.RtmMessage;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class LiveActivity extends RtcBaseActivity {

    private Schedules SCHEDULE;
    private VideoGridContainer mVideoGridContainer;
    private ImageView mMuteAudioBtn;
    private TextView participantCount, infoText;
    private CircularImageView userIcon;
    private TextView roomName;
    private Button decline, accept;
    private RecyclerView chatView;
    private EditText comments;
    private ImageButton send;
    private RelativeLayout permissionLayout;
    private int mChannelMemberCount = 1;

    private ChatManager mChatManager;
    private RtmClient mRtmClient;
    private ImageView mMuteVideoBtn;
    private RtmChannel mRtmChannel;

    private VideoEncoderConfiguration.VideoDimensions mVideoDimension;
    private MessageAdapter mMessageAdapter;
    private List<Chat> CHATS = new ArrayList<>();
    private boolean isBroadcaster;
    private boolean isPresentSomeOne;
    private Chat REQUESTED_CHAT = new Chat();
    private ImageView switchCamera;
    private int REMINDER_TIME = 0;
    private TimerTextView timerView;
    private ApiService restService;
    private String START_TIME = "";
    private String END_TIME = "";
    private Dialog dialog;
    private int SESSION_TIME = 20;
    private RelativeLayout autoHideLayout;
    private TransparentProgressDialog progressDialog;

    private Handler REMIND_HANDLER = new Handler();
    private Handler DELAY_DISCONNECT_CHECK_HANDLER = new Handler();


    private Runnable REMIND_RUNNABLE = new Runnable() {
        @Override
        public void run() {
            try {
                REMINDER_TIME--;
                if (REMINDER_TIME == 0) {
                    decline.performClick();
                    REMIND_HANDLER.removeCallbacksAndMessages(null);
                } else {
                    decline.setText(String.format("Decline(%s)", (REMINDER_TIME < 10) ? ("0" + REMINDER_TIME) : REMINDER_TIME));
                    REMIND_HANDLER.postDelayed(REMIND_RUNNABLE, 1000);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };

    private Handler SESSION_HANDLER = new Handler();
    private Runnable SESSION_RUNNABLE = new Runnable() {
        @Override
        public void run() {
            SESSION_TIME--;
            if (SESSION_TIME == 0) {
                autoHideLayout.setVisibility(View.INVISIBLE);
            }
            SESSION_HANDLER.postDelayed(SESSION_RUNNABLE, 1000);
        }
    };

    private String UPDATE_ID = "";
    private Handler UPDATE_HANDLER = new Handler();
    private Runnable UPDATE_RUNNABLE = new Runnable() {
        @Override
        public void run() {
            END_TIME = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(new Date());
            updateTime(SCHEDULE.getId(), timerView.getSeconds(), START_TIME, END_TIME, false);
        }
    };

    private Handler REQUEST_HANDLER = new Handler();
    private Runnable REQUEST_RUNNABLE = new Runnable() {
        @SuppressLint("SetTextI18n")
        @Override
        public void run() {
            try {
                accept.setText("Request");
                accept.setVisibility(View.VISIBLE);
                accept.setEnabled(true);
                decline.setVisibility(View.GONE);
                infoText.setText("Request permission to presentor");
                accept.setEnabled(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };

    @SuppressLint("ClickableViewAccessibility")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_live_room);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        mChatManager = ((MainApplication) getApplication()).getChatManager();
        mRtmClient = mChatManager.getRtmClient();
        restService = ((MainApplication) getApplication()).getClient();

        try {
            REQUEST_HANDLER.removeCallbacksAndMessages(null);
            REMIND_HANDLER.removeCallbacksAndMessages(null);
            SESSION_HANDLER.removeCallbacksAndMessages(null);
            UPDATE_HANDLER.removeCallbacksAndMessages(null);
        } catch (Exception e) {
            e.printStackTrace();
        }

        String mString = Objects.requireNonNull(getIntent().getExtras()).getString("SCHEDULE", "");
        Gson mGson = new Gson();
        SCHEDULE = mGson.fromJson(mString, new TypeToken<Schedules>() {
        }.getType());

        initUI();
        initData();

        try {
            AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
            if (am != null) {
                am.setStreamVolume(AudioManager.STREAM_MUSIC, am.getStreamMaxVolume(AudioManager.STREAM_MUSIC), 0);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        mChannelMemberCount = 1;
        participantCount.setText(String.format("%d", mChannelMemberCount));
        send.setOnClickListener(view -> {
            try {
                if ((mChannelMemberCount > 1 && mVideoGridContainer.getUserCount() > 0) || isBroadcaster) {
                    if (!comments.getText().toString().trim().isEmpty()) {
                        Chat chat = new Chat();
                        chat.setCanPresent(1);
                        chat.setRequest(false);
                        chat.setRequesPresent(false);
                        chat.setRequesProfile(false);
                        chat.setResponse(false);
                        chat.setResponsePresent(false);
                        chat.setResponseProfile(false);
                        String mTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(new Date());
                        chat.setDate(mTime);
                        chat.setMessage(comments.getText().toString().trim());
                        chat.setName(GlobalData.user.getData().getFname());
                        chat.setProfile(GlobalData.user.getData().getProfile_photo().trim());
                        chat.setId(isBroadcaster ? GlobalData.user.getData().getEmp_code().trim() : GlobalData.user.getData().getSmpin().trim());
                        Gson gson = new Gson();
                        JsonElement jsonElement = gson.toJsonTree(
                                chat, new TypeToken<Chat>() {
                                }.getType());
                        CHATS.add(chat);
                        mMessageAdapter.notifyItemRangeChanged(CHATS.size(), 1);
                        chatView.scrollToPosition(CHATS.size() - 1);
                        sendChannelMessage(jsonElement.toString());
                        postMessage(SCHEDULE.getId(), comments.getText().toString().trim());
                    }
                } else {
                    Toast.makeText(this, "Session not started!", Toast.LENGTH_SHORT).show();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            comments.setText("");
        });
        createAndJoinChannel();

        chatView.setOnTouchListener(new OnSwipeTouchListener(LiveActivity.this) {
            public void onSwipeTop() {
            }

            public void onSwipeRight() {

            }

            public void onSwipeLeft() {
                showLayout();
            }

            public void onSwipeBottom() {
            }
        });

        mVideoGridContainer.setOnTouchListener(new OnSwipeTouchListener(LiveActivity.this) {
            public void onSwipeTop() {
            }

            public void onSwipeRight() {
                showLayout();
            }

            public void onSwipeLeft() {

            }

            public void onSwipeBottom() {
            }
        });

        participantCount.setOnClickListener(view -> {
            if (!isBroadcaster) {
                return;
            }
            getActiveList(SCHEDULE.getId());
        });
        getChatList(SCHEDULE.getId());
        SESSION_HANDLER.postDelayed(SESSION_RUNNABLE, 1000);


        //Check Dismiss Handler 5 Minitues

        if (!isBroadcaster) {
            DELAY_DISCONNECT_CHECK_HANDLER.postDelayed(new Runnable() {

                @Override
                public void run() {
                    setOnLeaveProcess("DELAY_DISCONNECT_CHECK_HANDLER");
                }
            }, 300000);
        }


    }

    private void setOnLeaveProcess(String logPersonal) {
        REQUEST_HANDLER.removeCallbacksAndMessages(null);
        REMIND_HANDLER.removeCallbacksAndMessages(null);
        SESSION_HANDLER.removeCallbacksAndMessages(null);
        UPDATE_HANDLER.removeCallbacksAndMessages(null);
        DELAY_DISCONNECT_CHECK_HANDLER.removeCallbacksAndMessages(null);

        Log.e("logPersonal", logPersonal);
        //  Toast.makeText(LiveActivity.this, logPersonal, Toast.LENGTH_LONG).show();

        if (isBroadcaster || decline.getText().equals("Stop Presenting")) {
            stopBroadcast();
        }

        if (isBroadcaster) {
            sendOrganisorStatus(5);
        } else {
            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
            statsManager().clearAllData();
            leaveAndReleaseChannel();

            END_TIME = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(new Date());
            try {
                updateTime(SCHEDULE.getId(), timerView.getSeconds(), START_TIME, END_TIME, true);
            } catch (Exception e) {
                e.printStackTrace();
            }

            timerView.stopTimer();
        }


    }

    private void showLayout() {
        if (chatView.getVisibility() == View.VISIBLE) {
            chatView.animate()
                    .translationX(-chatView.getWidth())
                    .setDuration(500)
                    .setListener(new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            super.onAnimationEnd(animation);
                            chatView.setVisibility(View.GONE);
                        }
                    }).start();
        } else {
            chatView.animate()
                    .translationX(0)
                    .setDuration(500)
                    .setListener(new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            super.onAnimationEnd(animation);
                        }

                        @Override
                        public void onAnimationStart(Animator animation) {
                            super.onAnimationStart(animation);
                            chatView.setVisibility(View.VISIBLE);
                        }
                    }).start();
        }
    }

    @Override
    public void onUserInteraction() {
        super.onUserInteraction();
        SESSION_TIME = 20;
        if (autoHideLayout.getVisibility() == View.INVISIBLE) {
            autoHideLayout.setVisibility(View.VISIBLE);
        }
    }

    @Override
    public void onBackPressed() {

    }

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

    @SuppressLint("SetTextI18n")
    private void initUI() {

        roomName = findViewById(R.id.live_room_name);
        roomName.setText(config().getChannelName());
        roomName.setSelected(true);
        TextView trainingTitle = findViewById(R.id.trainingTitle);
        trainingTitle.setText(SCHEDULE.getTitle());

        participantCount = findViewById(R.id.participantCount);
        infoText = findViewById(R.id.infoText);
        decline = findViewById(R.id.decline);
        accept = findViewById(R.id.accept);
        chatView = findViewById(R.id.chatView);
        comments = findViewById(R.id.comments);
        send = findViewById(R.id.send);
        permissionLayout = findViewById(R.id.permissionLayout);
        userIcon = findViewById(R.id.live_name_board_icon);
        timerView = findViewById(R.id.timerView);
        timerView.startTimer();

        autoHideLayout = findViewById(R.id.autoHideLayout);

        String chatUserId = Objects.requireNonNull(getIntent().getExtras()).getString("CHAT_USER_ID");
        mChatManager.getRtmClient().login(null, chatUserId, new ResultCallback<Void>() {
            @Override
            public void onSuccess(Void aVoid) {
                Log.i("John", "login success");
            }

            @Override
            public void onFailure(ErrorInfo errorInfo) {
                Log.i("John", "login failed: " + errorInfo.getErrorCode());
            }
        });

        int role = getIntent().getIntExtra(
                com.cygnusa.hyperm.training.Constants.KEY_CLIENT_ROLE,
                Constants.CLIENT_ROLE_AUDIENCE);
        isBroadcaster = (role == Constants.CLIENT_ROLE_BROADCASTER);

        if (isBroadcaster) {
            roomName.setText(GlobalData.user.getData().getFname());
            Glide.with(this).load(GlobalData.user.getData().getProfile_photo())
                    .thumbnail(Glide.with(this).load(R.drawable.gif_loader))
                    .into(userIcon);
        }

        mMuteVideoBtn = findViewById(R.id.live_btn_mute_video);
        mMuteVideoBtn.setActivated(isBroadcaster);
        mMuteVideoBtn.setVisibility(isBroadcaster ? View.VISIBLE : View.INVISIBLE);

        mMuteAudioBtn = findViewById(R.id.live_btn_mute_audio);
        mMuteAudioBtn.setActivated(isBroadcaster);
        mMuteAudioBtn.setVisibility(isBroadcaster ? View.VISIBLE : View.INVISIBLE);

        switchCamera = findViewById(R.id.live_btn_switch_camera);
        switchCamera.setVisibility(isBroadcaster ? View.VISIBLE : View.INVISIBLE);

        CHATS = new ArrayList<>();
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(RecyclerView.VERTICAL);
        layoutManager.setStackFromEnd(true);

        mMessageAdapter = new MessageAdapter(this, CHATS);
        chatView.setLayoutManager(layoutManager);
        chatView.setAdapter(mMessageAdapter);

        rtcEngine().setBeautyEffectOptions(true,
                com.cygnusa.hyperm.training.Constants.DEFAULT_BEAUTY_OPTIONS);

        mVideoGridContainer = findViewById(R.id.live_video_grid_layout);
        mVideoGridContainer.setStatsManager(statsManager());

        if (isBroadcaster) {
            permissionLayout.setVisibility(View.INVISIBLE);
        } else {
            permissionLayout.setVisibility(View.VISIBLE);
            decline.setVisibility(View.GONE);
            accept.setText("Request");
            infoText.setText("Request permission to present");
        }

        accept.setOnClickListener(view -> {
            if (isBroadcaster) {
                REMIND_HANDLER.removeCallbacksAndMessages(null);
                REQUESTED_CHAT.setCanPresent(0);
                REQUESTED_CHAT.setRequest(false);
                REQUESTED_CHAT.setRequesPresent(false);
                REQUESTED_CHAT.setRequesProfile(false);
                REQUESTED_CHAT.setResponse(true);
                REQUESTED_CHAT.setResponsePresent(true);
                REQUESTED_CHAT.setResponseProfile(false);
                Gson gson = new Gson();
                JsonElement jsonElement = gson.toJsonTree(
                        REQUESTED_CHAT, new TypeToken<Chat>() {
                        }.getType());
                sendChannelMessage(jsonElement.toString());
                infoText.setText("Dismiss " + REQUESTED_CHAT.getFullName() + " presentation");
                decline.setText("Dismiss");
                decline.setVisibility(View.VISIBLE);
                accept.setVisibility(View.GONE);
            } else {
//                if (mChannelMemberCount > 1 && mVideoGridContainer.getUserCount() > 0) {
                Chat chat = new Chat();
                chat.setName(GlobalData.user.getData().getFullName());
                chat.setCanPresent(1);
                chat.setRequest(true);
                chat.setRequesPresent(true);
                chat.setRequesProfile(false);
                chat.setResponse(false);
                chat.setResponsePresent(false);
                chat.setResponseProfile(false);
                chat.setId(GlobalData.user.getData().getSmpin().trim());
                Gson gson = new Gson();
                JsonElement jsonElement = gson.toJsonTree(
                        chat, new TypeToken<Chat>() {
                        }.getType());
                sendChannelMessage(jsonElement.toString());
                accept.setText("Requested");
                accept.setEnabled(false);
                REQUEST_HANDLER.postDelayed(REQUEST_RUNNABLE, 20 * 1000);
//                } else {
//                    Toast.makeText(this, "Organisor not joined, try again!", Toast.LENGTH_SHORT).show();
//                }
            }
        });

        decline.setOnClickListener(view -> {
            if (isBroadcaster) {
                if (isPresentSomeOne && mVideoGridContainer.getUserCount() > 1) {
                    REQUESTED_CHAT.setCanPresent(2);
                    REQUESTED_CHAT.setRequest(false);
                    REQUESTED_CHAT.setRequesPresent(false);
                    REQUESTED_CHAT.setRequesProfile(false);
                    REQUESTED_CHAT.setResponse(true);
                    REQUESTED_CHAT.setResponsePresent(true);
                    REQUESTED_CHAT.setResponseProfile(false);
                    Gson gson = new Gson();
                    JsonElement jsonElement = gson.toJsonTree(
                            REQUESTED_CHAT, new TypeToken<Chat>() {
                            }.getType());
                    sendChannelMessage(jsonElement.toString());
                } else {
                    isPresentSomeOne = false;
                    REQUESTED_CHAT.setCanPresent(1);
                    REQUESTED_CHAT.setRequest(false);
                    REQUESTED_CHAT.setRequesPresent(false);
                    REQUESTED_CHAT.setRequesProfile(false);
                    REQUESTED_CHAT.setResponse(true);
                    REQUESTED_CHAT.setResponsePresent(true);
                    REQUESTED_CHAT.setResponseProfile(false);
                    Gson gson = new Gson();
                    JsonElement jsonElement = gson.toJsonTree(
                            REQUESTED_CHAT, new TypeToken<Chat>() {
                            }.getType());
                    sendChannelMessage(jsonElement.toString());
                    permissionLayout.setVisibility(View.INVISIBLE);
                    REMIND_HANDLER.removeCallbacksAndMessages(null);
                }
            } else {
                stopBroadcast();
                switchCamera.setVisibility(View.INVISIBLE);
                accept.setText("Request");
                accept.setVisibility(View.VISIBLE);
                accept.setEnabled(true);
                decline.setVisibility(View.GONE);
                mMuteAudioBtn.setVisibility(View.INVISIBLE);
                mMuteVideoBtn.setVisibility(View.INVISIBLE);
                infoText.setText("Request permission to presentor");
            }
        });

        START_TIME = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(new Date());
        END_TIME = START_TIME;
        UPDATE_HANDLER.post(UPDATE_RUNNABLE);

        rtcEngine().setClientRole(role);
        rtcEngine().setEnableSpeakerphone(true);
        rtcEngine().setDefaultAudioRoutetoSpeakerphone(true);
        rtcEngine().enableVideo();
        if (isBroadcaster) startBroadcast();
    }

    private void initData() {
        mVideoDimension = VideoEncoderConfiguration.VD_640x360;
    }

    @Override
    protected void onGlobalLayoutCompleted() {
        RelativeLayout topLayout = findViewById(R.id.live_room_top_layout);
        RelativeLayout.LayoutParams params =
                (RelativeLayout.LayoutParams) topLayout.getLayoutParams();
        params.height = mStatusBarHeight + topLayout.getMeasuredHeight();
        topLayout.setLayoutParams(params);
        topLayout.setPadding(0, mStatusBarHeight, 0, 0);
    }

    private void startBroadcast() {
        rtcEngine().setClientRole(Constants.CLIENT_ROLE_BROADCASTER);
        SurfaceView surface = prepareRtcVideo(0, true);
        mVideoGridContainer.addUserVideoSurface(0, surface, true);
        mMuteAudioBtn.setActivated(true);
    }

    private void stopBroadcast() {
        rtcEngine().setClientRole(Constants.CLIENT_ROLE_AUDIENCE);
        removeRtcVideo(0, true);
        mVideoGridContainer.removeUserVideo(0, true);
        mMuteAudioBtn.setActivated(false);
    }

    @Override
    public void onJoinChannelSuccess(String channel, int uid, int elapsed) {

    }

    @Override
    public void onUserJoined(int uid, int elapsed) {
        // Do nothing at the moment
    }

    @Override
    public void onUserOffline(final int uid, int reason) {
        runOnUiThread(() -> removeRemoteUser(uid));
    }

    @Override
    public void onFirstRemoteVideoDecoded(final int uid, int width, int height, int elapsed) {
        runOnUiThread(() -> renderRemoteUser(uid));
    }

    private void renderRemoteUser(int uid) {
        SurfaceView surface = prepareRtcVideo(uid, false);
        mVideoGridContainer.addUserVideoSurface(uid, surface, false);
    }

    private void removeRemoteUser(int uid) {
        removeRtcVideo(uid, false);
        mVideoGridContainer.removeUserVideo(uid, false);
        if (isBroadcaster) {
            if (isPresentSomeOne) {
                accept.setVisibility(View.VISIBLE);
                permissionLayout.setVisibility(View.INVISIBLE);
                isPresentSomeOne = false;
            }
        }
    }

    @Override
    public void onLocalVideoStats(IRtcEngineEventHandler.LocalVideoStats stats) {
        if (!statsManager().isEnabled()) return;

        LocalStatsData data = (LocalStatsData) statsManager().getStatsData(0);
        if (data == null) return;

        data.setWidth(mVideoDimension.width);
        data.setHeight(mVideoDimension.height);
        data.setFramerate(stats.sentFrameRate);
    }

    @Override
    public void onRtcStats(IRtcEngineEventHandler.RtcStats stats) {
        if (!statsManager().isEnabled()) return;

        LocalStatsData data = (LocalStatsData) statsManager().getStatsData(0);
        if (data == null) return;

        data.setLastMileDelay(stats.lastmileDelay);
        data.setVideoSendBitrate(stats.txVideoKBitRate);
        data.setVideoRecvBitrate(stats.rxVideoKBitRate);
        data.setAudioSendBitrate(stats.txAudioKBitRate);
        data.setAudioRecvBitrate(stats.rxAudioKBitRate);
        data.setCpuApp(stats.cpuAppUsage);
        data.setCpuTotal(stats.cpuAppUsage);
        data.setSendLoss(stats.txPacketLossRate);
        data.setRecvLoss(stats.rxPacketLossRate);
    }

    @Override
    public void onNetworkQuality(int uid, int txQuality, int rxQuality) {
        if (!statsManager().isEnabled()) return;

        StatsData data = statsManager().getStatsData(uid);
        if (data == null) return;

        data.setSendQuality(statsManager().qualityToString(txQuality));
        data.setRecvQuality(statsManager().qualityToString(rxQuality));
    }

    @Override
    public void onRemoteVideoStats(IRtcEngineEventHandler.RemoteVideoStats stats) {
        if (!statsManager().isEnabled()) return;

        RemoteStatsData data = (RemoteStatsData) statsManager().getStatsData(stats.uid);
        if (data == null) return;

        data.setWidth(stats.width);
        data.setHeight(stats.height);
        data.setFramerate(stats.rendererOutputFrameRate);
        data.setVideoDelay(stats.delay);
    }

    @Override
    public void onRemoteAudioStats(IRtcEngineEventHandler.RemoteAudioStats stats) {
        if (!statsManager().isEnabled()) return;

        RemoteStatsData data = (RemoteStatsData) statsManager().getStatsData(stats.uid);
        if (data == null) return;

        data.setAudioNetDelay(stats.networkTransportDelay);
        data.setAudioNetJitter(stats.jitterBufferDelay);
        data.setAudioLoss(stats.audioLossRate);
        data.setAudioQuality(statsManager().qualityToString(stats.quality));
    }

    public void onLeaveClicked(View view) {
        setOnLeaveProcess("OnLeaveClicked");
    }

    public void onSwitchCameraClicked(View view) {
        rtcEngine().switchCamera();
    }

    public void onMuteAudioClicked(View view) {
        rtcEngine().muteLocalAudioStream(view.isActivated());
        view.setActivated(!view.isActivated());
    }

    @SuppressLint("SourceLockedOrientationActivity")
    public void onSwitchSpeakerClicked(View view) {
        rtcEngine().setEnableSpeakerphone(!rtcEngine().isSpeakerphoneEnabled());
        ImageView iv = findViewById(R.id.switch_speaker_id);
        if (rtcEngine().isSpeakerphoneEnabled()) {
            iv.setImageResource(R.drawable.btn_speaker);
            iv.setBackgroundResource(R.drawable.rounded_bg_full_transparent);
        } else {
            iv.setImageResource(R.drawable.btn_speaker_off);
            iv.setBackgroundResource(R.drawable.rounded_bg_half_transparent);
        }
    }

    public void onMuteVideoClicked(View view) {
        rtcEngine().muteLocalVideoStream(view.isActivated());
        if (view.isActivated()) {
            rtcEngine().enableLocalVideo(false);
        } else {
            rtcEngine().enableLocalVideo(true);
        }
        view.setActivated(!view.isActivated());
    }

    private void createAndJoinChannel() {
        mRtmChannel = mRtmClient.createChannel(config().getChannelName(), new MyChannelListener());
        if (mRtmChannel == null) {
            return;
        }

        mRtmChannel.join(new ResultCallback<Void>() {
            @Override
            public void onSuccess(Void responseInfo) {
                getChannelMemberList();
                if (isBroadcaster) {
                    sendProfile();
                } else {
                    requestProfile();
                }
            }

            @Override
            public void onFailure(ErrorInfo errorInfo) {

            }
        });
    }

    private void sendProfile() {
        Chat chat = new Chat();
        chat.setId("All");
        chat.setProfile(GlobalData.user.getData().getProfile_photo());
        chat.setName(GlobalData.user.getData().getFname());
        chat.setCanPresent(1);
        chat.setRequest(false);
        chat.setRequesPresent(false);
        chat.setRequesProfile(false);
        chat.setResponse(true);
        chat.setResponsePresent(false);
        chat.setResponseProfile(true);
        Gson gson = new Gson();
        JsonElement jsonElement = gson.toJsonTree(
                chat, new TypeToken<Chat>() {
                }.getType());
        sendChannelMessage(jsonElement.toString());
        sendOrganisorStatus(4);
    }

    private void sendOrganisorStatus(int canPresent) {
        Chat chat = new Chat();
        chat.setId("All");
        chat.setProfile(GlobalData.user.getData().getProfile_photo());
        chat.setName(GlobalData.user.getData().getFname());
        chat.setCanPresent(canPresent);
        chat.setRequest(false);
        chat.setRequesPresent(false);
        chat.setRequesProfile(false);
        chat.setResponse(true);
        chat.setResponsePresent(true);
        chat.setResponseProfile(false);
        Gson gson = new Gson();
        JsonElement jsonElement = gson.toJsonTree(
                chat, new TypeToken<Chat>() {
                }.getType());
        sendChannelMessage(jsonElement.toString());
        if (canPresent == 5) {
            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
            statsManager().clearAllData();
            leaveAndReleaseChannel();

            END_TIME = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(new Date());
            updateTime(SCHEDULE.getId(), timerView.getSeconds(), START_TIME, END_TIME, true);
            timerView.stopTimer();
        }
    }

    private void requestProfile() {
        Chat chat = new Chat();
        chat.setId(GlobalData.user.getData().getSmpin());
        chat.setCanPresent(1);
        chat.setRequest(true);
        chat.setRequesPresent(false);
        chat.setRequesProfile(true);
        chat.setResponse(false);
        chat.setResponsePresent(false);
        chat.setResponseProfile(false);
        Gson gson = new Gson();
        JsonElement jsonElement = gson.toJsonTree(
                chat, new TypeToken<Chat>() {
                }.getType());
        sendChannelMessage(jsonElement.toString());
    }

    private void getChannelMemberList() {
        mRtmChannel.getMembers(new ResultCallback<List<RtmChannelMember>>() {
            @Override
            public void onSuccess(final List<RtmChannelMember> responseInfo) {
                runOnUiThread(() -> {
                    mChannelMemberCount = responseInfo.size();
                    participantCount.setText(String.format("%d", mChannelMemberCount));
                });
            }

            @Override
            public void onFailure(ErrorInfo errorInfo) {
            }
        });
    }

    private void sendChannelMessage(String content) {
        RtmMessage message = mRtmClient.createMessage();
        message.setText(content);
        mRtmChannel.sendMessage(message, new ResultCallback<Void>() {
            @Override
            public void onSuccess(Void aVoid) {

            }

            @Override
            public void onFailure(ErrorInfo errorInfo) {
                Log.i("John", "message failed: " + errorInfo.getErrorCode());
            }
        });
    }

    private void leaveAndReleaseChannel() {
        try {
            if (mRtmChannel != null) {
                mRtmChannel.leave(null);
                mRtmChannel.release();
                mRtmChannel = null;
            }
            mChatManager.getRtmClient().logout(new ResultCallback<Void>() {
                @Override
                public void onSuccess(Void aVoid) {

                }

                @Override
                public void onFailure(ErrorInfo errorInfo) {

                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    class MyChannelListener implements RtmChannelListener {
        @Override
        public void onMemberCountUpdated(int i) {

        }

        @Override
        public void onAttributesUpdated(List<RtmChannelAttribute> list) {

        }

        @SuppressLint({"SetTextI18n", "SourceLockedOrientationActivity"})
        @Override
        public void onMessageReceived(final RtmMessage message, final RtmChannelMember fromMember) {
            runOnUiThread(() -> {
                try {
                    String msg = message.getText();
                    Gson gson = new Gson();
                    Chat chat = gson.fromJson(msg, new TypeToken<Chat>() {
                    }.getType());

                    if (chat.isRequest()) {
                        if (isBroadcaster) {
                            if (chat.isRequesProfile()) {
                                sendProfile(chat);
                            } else if (chat.isRequesPresent()) {
                                if (isPresentSomeOne) {
                                    sendSomeonePresent(chat);
                                } else {
                                    isPresentSomeOne = true;
                                    REQUESTED_CHAT = chat;
                                    enabelPermissionLayout();
                                }
                            }
                        }
                    } else if (chat.isResponse()) {
                        if (!isBroadcaster) {
                            if (chat.isResponseProfile()) {
                                setProfile(chat);
                            } else if (chat.isResponsePresent()) {
                                if (chat.getCanPresent() == 0) { //Accept
                                    startPresent(chat);
                                } else if (chat.getCanPresent() == 1) { //Decline
                                    declinePresent(chat);
                                } else if (chat.getCanPresent() == 2) { //Dismiss
                                    dismissPresent(chat);
                                } else if (chat.getCanPresent() == 3) { //Someone Present
                                    String id = GlobalData.user.getData().getSmpin().trim();
                                    if (id.equalsIgnoreCase(chat.getId())) {
                                        Toast.makeText(LiveActivity.this, "Someone was presenting, try again!", Toast.LENGTH_SHORT).show();
                                        permissionLayout.setVisibility(View.VISIBLE);
                                        decline.setVisibility(View.GONE);
                                        accept.setText("Request");
                                        infoText.setText("Request permission to present");
                                        accept.setEnabled(true);
                                    }
                                } else if (chat.getCanPresent() == 4) { //Restart
                                    try {
                                        DELAY_DISCONNECT_CHECK_HANDLER.removeCallbacksAndMessages(null);
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                } else if (chat.getCanPresent() == 5) {
                                    //Check Dismiss Handler 3 Minitues
                                    DELAY_DISCONNECT_CHECK_HANDLER.postDelayed(new Runnable() {
                                        @Override
                                        public void run() {
                                            setOnLeaveProcess("DELAY_DISCONNECT_CHECK_HANDLER 3 Minitues");
                                        }
                                    }, 180000);
                                } else if (chat.getCanPresent() == 6) { //Dismiss
                                    try {
                                        DELAY_DISCONNECT_CHECK_HANDLER.removeCallbacksAndMessages(null);
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                                } else if (chat.getCanPresent() == 7) { //Dismiss
                                    try {
                                        DELAY_DISCONNECT_CHECK_HANDLER.removeCallbacksAndMessages(null);
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                                }
                            }
                        }
                    } else {
                        CHATS.add(chat);
                        mMessageAdapter.notifyItemRangeChanged(CHATS.size(), 1);
                        chatView.scrollToPosition(CHATS.size() - 1);
                        SESSION_TIME = Math.max(SESSION_TIME, 5);
                        if (autoHideLayout.getVisibility() == View.INVISIBLE) {
                            autoHideLayout.setVisibility(View.VISIBLE);
                        }
                    }
                } catch (JsonSyntaxException e) {
                    e.printStackTrace();
                }
            });
        }

        @Override
        public void onMemberJoined(RtmChannelMember member) {
            runOnUiThread(() -> {
                mChannelMemberCount++;
                participantCount.setText(String.format("%d", mChannelMemberCount));
            });
        }

        @Override
        public void onMemberLeft(RtmChannelMember member) {
            runOnUiThread(() -> {
                mChannelMemberCount--;
                participantCount.setText(String.format("%d", mChannelMemberCount));
            });
        }
    }

    @SuppressLint("SetTextI18n")
    private void dismissPresent(Chat chat) {
        String id = GlobalData.user.getData().getSmpin().trim();
        if (id.equalsIgnoreCase(chat.getId())) {
            stopBroadcast();
            Toast.makeText(this, "Organisor dismissed your presentation", Toast.LENGTH_SHORT).show();
            accept.setText("Request");
            accept.setEnabled(true);
            accept.setVisibility(View.VISIBLE);
            decline.setVisibility(View.GONE);
            switchCamera.setVisibility(View.INVISIBLE);
            infoText.setText("Request permission to presentor");
            accept.setEnabled(true);
        }
    }

    @SuppressLint("SetTextI18n")
    private void declinePresent(Chat chat) {
        String id = GlobalData.user.getData().getSmpin().trim();
        if (id.equalsIgnoreCase(chat.getId())) {
            REQUEST_HANDLER.removeCallbacksAndMessages(null);
            Toast.makeText(this, "Organisor is not accepted your request", Toast.LENGTH_SHORT).show();
            accept.setText("Request");
            accept.setVisibility(View.VISIBLE);
            accept.setEnabled(true);
            decline.setVisibility(View.GONE);
            infoText.setText("Request permission to presentor");
            accept.setEnabled(true);
        }
    }

    @SuppressLint("SetTextI18n")
    private void startPresent(Chat chat) {
        String id = GlobalData.user.getData().getSmpin().trim();
        if (id.equalsIgnoreCase(chat.getId())) {
            REQUEST_HANDLER.removeCallbacksAndMessages(null);
            REQUESTED_CHAT = chat;
            startBroadcast();
            accept.setVisibility(View.GONE);
            switchCamera.setVisibility(View.VISIBLE);
            mMuteAudioBtn.setVisibility(View.VISIBLE);
            mMuteVideoBtn.setVisibility(View.VISIBLE);
            decline.setVisibility(View.VISIBLE);
            decline.setText("Stop Presenting");
            infoText.setText("");
        }
    }

    @SuppressLint("SetTextI18n")
    private void enabelPermissionLayout() {
        SESSION_TIME = 20;
        if (autoHideLayout.getVisibility() == View.INVISIBLE) {
            autoHideLayout.setVisibility(View.VISIBLE);
        }
        permissionLayout.setVisibility(View.VISIBLE);
        infoText.setText(REQUESTED_CHAT.getFullName() + " wants to present");
        accept.setVisibility(View.VISIBLE);
        decline.setVisibility(View.VISIBLE);
        accept.setText("Accept");
        REMINDER_TIME = 15;
        REMIND_HANDLER.post(REMIND_RUNNABLE);
        accept.setEnabled(true);
    }

    private void sendSomeonePresent(Chat chat) {
        chat.setCanPresent(3);
        chat.setRequest(false);
        chat.setRequesPresent(false);
        chat.setRequesProfile(false);
        chat.setResponse(true);
        chat.setResponsePresent(true);
        chat.setResponseProfile(false);
        Gson gson = new Gson();
        JsonElement jsonElement = gson.toJsonTree(
                chat, new TypeToken<Chat>() {
                }.getType());
        sendChannelMessage(jsonElement.toString());
    }

    private void setProfile(Chat chat) {
        if (chat.getId().equalsIgnoreCase("All")) {
            roomName.setText(chat.getName());
            Glide.with(this).load(chat.getProfile())
                    .thumbnail(Glide.with(this).load(R.drawable.gif_loader))
                    .into(userIcon);
        } else {
            String id = GlobalData.user.getData().getSmpin().trim();
            if (id.equalsIgnoreCase(chat.getId())) {
                roomName.setText(chat.getName());
                Glide.with(this).load(chat.getProfile())
                        .thumbnail(Glide.with(this).load(R.drawable.gif_loader))
                        .into(userIcon);
            }
        }
    }

    private void sendProfile(Chat chat) {
        chat.setProfile(GlobalData.user.getData().getProfile_photo());
        chat.setName(GlobalData.user.getData().getFname());

        chat.setCanPresent(1);
        chat.setRequest(false);
        chat.setRequesPresent(false);
        chat.setRequesProfile(false);
        chat.setResponse(true);
        chat.setResponsePresent(false);
        chat.setResponseProfile(true);
        Gson gson = new Gson();
        JsonElement jsonElement = gson.toJsonTree(
                chat, new TypeToken<Chat>() {
                }.getType());
        sendChannelMessage(jsonElement.toString());
        sendOrganisorStatus(4);
    }

    private void updateTime(String tId, int seconds, String startTime, String endTime, boolean isEnd) {
        if (new UtilService().isNetworkAvailable(Objects.requireNonNull(LiveActivity.this))) {

            if (isEnd) {
                progressDialog = new TransparentProgressDialog(LiveActivity.this);
                progressDialog.show();
            }

            try {
                long diffInMs = Objects.requireNonNull(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
                        .parse(endTime)).getTime() - Objects.requireNonNull(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
                        .parse(startTime)).getTime();
                seconds = (int) TimeUnit.MILLISECONDS.toSeconds(diffInMs);
            } catch (Exception e) {
                e.printStackTrace();
            }

            try {
                HashMap<String, String> map = new HashMap<>();
                map.put("sid", tId);
                map.put("id", UPDATE_ID);
                map.put("timetaken", String.valueOf(seconds));
                map.put("fromtime", startTime);
                map.put("totime", endTime);

                restService.updateTime(map).enqueue(new MyCallback<CommonResponse>(isEnd) {
                    @Override
                    public void onResponse(Call<CommonResponse> call, Response<CommonResponse> response) {
                        UPDATE_HANDLER.removeCallbacksAndMessages(null);
                        if (progressDialog != null && progressDialog.isShowing()) {
                            progressDialog.dismiss();
                        }
                        if (response.body() != null) {
                            if (response.body().getStatus() == 200 && response.body().getResponse().equalsIgnoreCase("failed")) {
                                setOnLeaveProcess("updateTime Service");
                            } else {
                                UPDATE_ID = Objects.requireNonNull(response.body()).getData().toString();
                                if (isEnd) {
                                    finish();
                                } else {
                                    UPDATE_HANDLER.postDelayed(UPDATE_RUNNABLE, 60 * 1000);
                                }
                            }
                        } else {
                            if (isEnd) {
                                finish();
                            } else {
                                UPDATE_HANDLER.postDelayed(UPDATE_RUNNABLE, 60 * 1000);
                            }
                        }
                    }

                    @Override
                    public void onFailure(Call<CommonResponse> call, Throwable t) {
                        if (progressDialog != null && progressDialog.isShowing()) {
                            progressDialog.dismiss();
                        }
                        UPDATE_HANDLER.removeCallbacksAndMessages(null);
                        DELAY_DISCONNECT_CHECK_HANDLER.removeCallbacksAndMessages(null);

                        if (isEnd) {
                            finish();
                        } else {
                            UPDATE_HANDLER.postDelayed(UPDATE_RUNNABLE, 60 * 1000);
                        }
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();

                if (progressDialog != null && progressDialog.isShowing()) {
                    progressDialog.dismiss();
                }
                UPDATE_HANDLER.removeCallbacksAndMessages(null);

                if (isEnd) {
                    finish();
                } else {
                    UPDATE_HANDLER.postDelayed(UPDATE_RUNNABLE, 60 * 1000);
                }
            }
        }
    }

    private void postMessage(String tId, String message) {
        if (new UtilService().isNetworkAvailable(Objects.requireNonNull(LiveActivity.this))) {
            try {
                HashMap<String, String> map = new HashMap<>();
                map.put("sid", tId);
                map.put("msg", message);
                restService.postMessage(map).enqueue(new Callback<CommonResponse>() {
                    @Override
                    public void onResponse(Call<CommonResponse> call, Response<CommonResponse> response) {

                    }

                    @Override
                    public void onFailure(Call<CommonResponse> call, Throwable t) {

                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void getChatList(String tID) {
        if (new UtilService().isNetworkAvailable(Objects.requireNonNull(LiveActivity.this))) {
            try {
                restService.getChatList(tID).enqueue(new Callback<ChatResponse>() {
                    @Override
                    public void onResponse(Call<ChatResponse> call, Response<ChatResponse> response) {
                        if (response.body() != null && response.body().getStatus() == 200) {
                            if (response.body().getData() != null && response.body().getData().size() > 0) {
                                CHATS.addAll(response.body().getData());
                                mMessageAdapter.notifyItemRangeChanged(CHATS.size(), 1);
                            }
                        }
                    }

                    @Override
                    public void onFailure(Call<ChatResponse> call, Throwable t) {

                    }
                });

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void getActiveList(String trainingId) {
        if (new UtilService().isNetworkAvailable(Objects.requireNonNull(LiveActivity.this))) {
            try {
                progressDialog = new TransparentProgressDialog(LiveActivity.this);
                progressDialog.setCancelable(true);
                progressDialog.show();

                restService.getActiveList(trainingId).enqueue(new Callback<ActiveResponse>() {
                    @Override
                    public void onResponse(Call<ActiveResponse> call, Response<ActiveResponse> response) {
                        if (progressDialog != null && progressDialog.isShowing()) {
                            progressDialog.dismiss();
                        }

                        if (response.body() != null && response.body().getStatus() == 200) {
                            if (response.body().getData() != null && response.body().getData().size() > 0) {
                                showActiveUser(response.body().getData());
                            } else {
                                Toast.makeText(LiveActivity.this, "Unable to get active user, try again!", Toast.LENGTH_SHORT).show();
                            }
                        }
                    }

                    @Override
                    public void onFailure(Call<ActiveResponse> call, Throwable t) {
                        t.printStackTrace();
                        if (progressDialog != null && progressDialog.isShowing()) {
                            progressDialog.dismiss();
                        }
                    }
                });

            } catch (Exception e) {
                e.printStackTrace();
                if (progressDialog != null && progressDialog.isShowing()) {
                    progressDialog.dismiss();
                }
            }
        }
    }

    @SuppressLint("SetTextI18n")
    private void showActiveUser(ArrayList<DSE> userList) {
        try {
            if (dialog != null && dialog.isShowing()) {
                dialog.dismiss();
            }

            AlertDialog.Builder builder = new AlertDialog.Builder(LiveActivity.this);
            Collections.sort(userList, (abc1, abc2) -> Boolean.compare(abc2.isActive(), abc1.isActive()));

            View mView = LayoutInflater.from(LiveActivity.this).inflate(R.layout.training_popup, null);
            ImageButton close = mView.findViewById(R.id.closeButton);
            TextView title = mView.findViewById(R.id.title);
            ListView modeList = mView.findViewById(R.id.listView);
            title.setText("Participants");
            close.setOnClickListener(view1 -> dialog.dismiss());
            String profile = GlobalData.user.getData().getProfile_photo();
            AttendanceAdapter modeAdapter = new AttendanceAdapter(LiveActivity.this, userList,
                    SCHEDULE.getOrganiser_name(), profile);
            modeList.setAdapter(modeAdapter);
            builder.setView(mView);
            dialog = builder.create();
            dialog.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
