package com.qboxus.tictic.activitesfragments.livestreaming.activities;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.LinearSnapHelper;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SnapHelper;

import com.facebook.drawee.view.SimpleDraweeView;
import com.qboxus.tictic.R;
import com.qboxus.tictic.activitesfragments.EditTextSheetFragment;
import com.qboxus.tictic.activitesfragments.livestreaming.adapter.LiveCommentsAdapter;
import com.qboxus.tictic.activitesfragments.livestreaming.adapter.LiveUserViewAdapter;
import com.qboxus.tictic.activitesfragments.livestreaming.fragments.InviteContactsToStreamFragment;
import com.qboxus.tictic.activitesfragments.livestreaming.model.CameraRequestModel;
import com.qboxus.tictic.activitesfragments.livestreaming.model.LiveCoinsModel;
import com.qboxus.tictic.activitesfragments.livestreaming.model.LiveCommentModel;
import com.qboxus.tictic.activitesfragments.livestreaming.model.LiveUserModel;
import com.qboxus.tictic.activitesfragments.livestreaming.stats.LocalStatsData;
import com.qboxus.tictic.activitesfragments.livestreaming.stats.RemoteStatsData;
import com.qboxus.tictic.activitesfragments.livestreaming.stats.StatsData;
import com.qboxus.tictic.activitesfragments.livestreaming.ui.VideoGridContainer;
import com.qboxus.tictic.activitesfragments.sendgift.StickerModel;
import com.qboxus.tictic.activitesfragments.shoping.adapter.StreamingProductsAdapter;
import com.qboxus.tictic.activitesfragments.shoping.models.ProductModel;
import com.qboxus.tictic.apiclasses.ApiLinks;
import com.qboxus.tictic.databinding.ActivitySingleCastStreamerBinding;
import com.qboxus.tictic.interfaces.AdapterClickListener;
import com.qboxus.tictic.interfaces.FragmentCallBack;
import com.qboxus.tictic.models.StreamJoinModel;
import com.qboxus.tictic.models.StreamShowHeartModel;
import com.qboxus.tictic.models.UserModel;
import com.qboxus.tictic.simpleclasses.DateOprations;
import com.qboxus.tictic.simpleclasses.Functions;
import com.qboxus.tictic.simpleclasses.OnSwipeTouchListener;
import com.qboxus.tictic.simpleclasses.Variables;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import com.volley.plus.VPackages.VolleyRequest;
import com.volley.plus.interfaces.Callback;

import org.json.JSONObject;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;

import io.agora.rtc2.Constants;
import io.agora.rtc2.IRtcEngineEventHandler;
import io.agora.rtc2.video.VideoEncoderConfiguration;

public class SingleCastStreamer extends RtcBaseActivity implements View.OnClickListener {

    private final long DELAY = 20000;
    DatabaseReference rootref;
    String userId, userName, userPicture;
    int userRole;
    String onlineType, description, secureCode, streamingId;
    int joinStreamPrice;
    boolean dualStreaming;
    LiveUserModel streamerLiveModel;
    Context context;
    boolean isFirstTimeFlip = true;
    View tabMainView;
    LiveUserViewAdapter liveUserViewAdapter;
    ArrayList<ProductModel> pList = new ArrayList<>();
    ActivitySingleCastStreamerBinding binding;
    // initailze the adapter
    ArrayList<LiveCommentModel> dataList = new ArrayList<>();
    LiveCommentsAdapter adapter;
    ChildEventListener commentChildListener;
    Calendar current_cal;
    ValueEventListener productChildListener;
    // initailze the adapter
    ArrayList<ProductModel> productsList = new ArrayList<>();
    StreamingProductsAdapter productsAdapter;
    ArrayList<StreamJoinModel> jointUserList = new ArrayList<>();
    ValueEventListener joinValueEventListener;
    ChildEventListener likeValueEventListener;
    int heartCounter = 0;
    ValueEventListener connectCheckListener;
    DatabaseReference connectedRef;
    ValueEventListener coinValueEventListener;
    ArrayList<LiveCoinsModel> senderCoinsList = new ArrayList<>();
    // check the current live user status eighter user is live or not when users goes offline this callback will hit
    ValueEventListener broadcastValueEventListener;
    ArrayList<UserModel> taggedUserList = new ArrayList<>();
    boolean isAudioActivated = true, isVideoActivated = true, isbeautyActivated = true;
    SimpleDraweeView ivGiftProfile, ivGiftItem;
    LinearLayout tabGiftTitle;
    RelativeLayout tabGiftMain;
    View animationGiftCapture, animationResetAnimation;
    TextView tvGiftTitle, tvGiftCountTitle, tvSendGiftCount;
    MediaPlayer player;
    Handler handler;
    ValueEventListener cameraRequestEventListener;
    private VideoGridContainer mVideoGridContainer;
    private VideoEncoderConfiguration.VideoDimensions mVideoDimension;
    private Timer timer = new Timer();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Functions.setLocale(Functions.getSharedPreference(this).getString(Variables.APP_LANGUAGE_CODE, Variables.DEFAULT_LANGUAGE_CODE)
                , this, getClass(), false);

        binding = DataBindingUtil.setContentView(SingleCastStreamer.this,
                R.layout.activity_single_cast_streamer);

        context = SingleCastStreamer.this;
        rootref = FirebaseDatabase.getInstance().getReference();
        rootref.keepSynced(true);

        Intent bundle = getIntent();
        if (bundle != null) {
            userId = bundle.getStringExtra("userId");
            userName = bundle.getStringExtra("userName");
            userPicture = bundle.getStringExtra("userPicture");
            userRole = Constants.CLIENT_ROLE_BROADCASTER;
            onlineType = "oneTwoOne";
            description = "";
            secureCode = "";
            dualStreaming = bundle.getBooleanExtra("dualStreaming", false);
            joinStreamPrice = bundle.getIntExtra("joinStreamPrice", 0);
            streamingId = bundle.getStringExtra("streamingId");
        }

        InitControl();
        ActionControl();

        if (userRole == Constants.CLIENT_ROLE_BROADCASTER) {
            rootref.child("LiveStreamingUsers").child(streamingId).keepSynced(true);
            rootref.child("LiveStreamingUsers").child(streamingId).onDisconnect().removeValue();

            addFirebaseNode();
            sendLiveNotification();
            broadcasterlistenerNode();
            addNodeCameraRequest();
        }
        ListenerCoinNode();
        addLikeStream();
        ListenerJoinNode();
        ListCommentData();
        addProductListener();
        addStreamInternetConnection();
        setUpScreenData();

    }

    private void setUpScreenData() {
        binding.tvCoinCount.setText(Functions.getSharedPreference(context).getString(Variables.U_WALLET, "0"));
        binding.ivMainProfile.setController(Functions.frescoImageLoad(userPicture, binding.ivMainProfile, false));
        binding.tvUserName.setText(userName);
        int verified = Functions.getSharedPreference(context).getInt(Variables.IS_VERIFIED, 0);
        if (verified==1) {
            binding.ivVerified.setVisibility(View.VISIBLE);
        } else {
            binding.ivVerified.setVisibility(View.GONE);
        }
    }

    private void InitControl() {
        binding.tabLikeStreaming.setOnClickListener(this);
        tabMainView = findViewById(R.id.tabMainView);
//        binding.streamLikeView.setOnClickListener(this);
        binding.tabShareStream.setOnClickListener(this);
        binding.tvMessage.setOnClickListener(this);

        initCommentAdapter();
        setUpJoinRecycler();
        initUI();
        initData();
    }

    private void ActionControl() {
        findViewById(R.id.cross_btn).setOnClickListener(this);

        final Animation inAnim = AnimationUtils.loadAnimation(context, R.anim.in_from_right);
        final Animation outAnim = AnimationUtils.loadAnimation(context, R.anim.out_to_left);
        final Animation inPrevAnim = AnimationUtils.loadAnimation(context, R.anim.in_from_left);
        final Animation outPrevAnim = AnimationUtils.loadAnimation(context, R.anim.out_to_right);


        tabMainView.setOnTouchListener(new OnSwipeTouchListener(context) {
            public void onSwipeTop() {

            }

            public void onSwipeRight() {

                binding.viewflliper.setInAnimation(inPrevAnim);
                binding.viewflliper.setOutAnimation(outPrevAnim);
                binding.innerViewflliper.setInAnimation(inPrevAnim);
                binding.innerViewflliper.setOutAnimation(outPrevAnim);
                Log.d(com.qboxus.tictic.Constants.tag, "start");

                if (binding.viewTwo == binding.viewflliper.getCurrentView()) {
                    if (binding.viewFour == binding.innerViewflliper.getCurrentView()) {
                        binding.innerViewflliper.showPrevious();
                    } else {
                        binding.viewflliper.showPrevious();
                    }
                } else {
                    binding.viewflliper.showPrevious();
                }

            }

            public void onSwipeLeft() {
                binding.viewflliper.setInAnimation(inAnim);
                binding.viewflliper.setOutAnimation(outAnim);
                binding.innerViewflliper.setInAnimation(inAnim);
                binding.innerViewflliper.setOutAnimation(outAnim);
                Log.d(com.qboxus.tictic.Constants.tag, "end");
                if (binding.viewTwo == binding.viewflliper.getCurrentView()) {
                    if (binding.viewThree == binding.innerViewflliper.getCurrentView()) {
                        binding.innerViewflliper.showNext();
                    }

                } else {
                    binding.viewflliper.showNext();
                }
            }

            public void onSwipeBottom() {

            }

            public void onDoubleClick() {

            }

            public void onSingleClick() {

            }
        });

        if (isFirstTimeFlip) {
            isFirstTimeFlip = false;
            if (binding.viewOne == binding.viewflliper.getCurrentView()) {
                binding.viewflliper.showNext();
            }
        }

        binding.tabEffects.setOnClickListener(this);
        binding.tabMenu.setOnClickListener(this);
        binding.ivVideoRequest.setOnClickListener(this);

    }

    public void initCommentAdapter() {
        dataList.clear();

        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context);
        linearLayoutManager.setStackFromEnd(true);
        binding.recylerview.setLayoutManager(linearLayoutManager);

        binding.recylerview.setHasFixedSize(true);

        adapter = new LiveCommentsAdapter(context, dataList, new AdapterClickListener() {
            @Override
            public void onItemClick(View view, int pos, Object object) {

            }
        });
        binding.recylerview.setAdapter(adapter);

    }

    public void ListCommentData() {
        current_cal = Calendar.getInstance();
        if (commentChildListener == null) {
            commentChildListener = new ChildEventListener() {
                @Override
                public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
                    LiveCommentModel model = dataSnapshot.getValue(LiveCommentModel.class);
                    dataList.add(model);

                    if (DateOprations.checkTimeDiffernce(current_cal, model.getCommentTime())) {
                        if (model.getType().equalsIgnoreCase("gift")) {
                            SingleCastStreamer.this.runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    ShowGiftAnimation(model);
                                }
                            });
                        }
                    }


                    adapter.notifyDataSetChanged();
                    binding.recylerview.scrollToPosition(dataList.size() - 1);

                }

                @Override
                public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

                }

                @Override
                public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
                }

                @Override
                public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

                }

                @Override
                public void onCancelled(@NonNull DatabaseError databaseError) {

                }
            };
            rootref.child("LiveStreamingUsers").child(streamingId).child("Chat").addChildEventListener(commentChildListener);
        }
    }

    public void removeCommentListener() {
        if (rootref != null && commentChildListener != null) {
            rootref.child("LiveStreamingUsers").child(streamingId).child("Chat").removeEventListener(commentChildListener);
            commentChildListener = null;
        }
    }

    public void addProductListener() {
        if (productChildListener == null) {
            initproductAdapter();
            Functions.printLog(com.qboxus.tictic.Constants.tag, "addProductListener");

            productChildListener = new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                    Functions.printLog(com.qboxus.tictic.Constants.tag, dataSnapshot.toString());
                    productsList.clear();
                    if (dataSnapshot.exists()) {
                        binding.productRecylerVeiw.setVisibility(View.VISIBLE);
                        for (DataSnapshot product : dataSnapshot.getChildren()) {
//                            AllBusinessMenuModel model = product.getValue(AllBusinessMenuModel.class);
//                            productsList.add(model);


                        }
                        productsAdapter.notifyDataSetChanged();

                    } else {

                        binding.productRecylerVeiw.setVisibility(View.GONE);
                    }
                }

                @Override
                public void onCancelled(@NonNull DatabaseError databaseError) {
                    Functions.printLog(com.qboxus.tictic.Constants.tag, databaseError.toString());
                    binding.productRecylerVeiw.setVisibility(View.GONE);
                }
            };

            rootref.child("LiveStreamingUsers").child(streamingId).child("productsList").addValueEventListener(productChildListener);
        }
    }

    public void removeProductListener() {
        if (rootref != null && productChildListener != null) {
            rootref.child("LiveStreamingUsers").child(streamingId).child("productsList").removeEventListener(productChildListener);
            productChildListener = null;
        }
    }

    public void initproductAdapter() {

        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false);
        binding.productRecylerVeiw.setLayoutManager(linearLayoutManager);
        binding.productRecylerVeiw.setHasFixedSize(true);

        SnapHelper snapHelper = new LinearSnapHelper();
        snapHelper.attachToRecyclerView(binding.productRecylerVeiw);


        productsAdapter = new StreamingProductsAdapter(context, productsList, new AdapterClickListener() {
            @Override
            public void onItemClick(View view, int pos, Object object) {

            }
        });
        binding.productRecylerVeiw.setAdapter(productsAdapter);

    }

    private void setUpJoinRecycler() {
        GridLayoutManager layoutManager = new GridLayoutManager(context, 2);
        layoutManager.setOrientation(RecyclerView.VERTICAL);
        binding.liveUserViewRecyclerView.setLayoutManager(layoutManager);
        liveUserViewAdapter = new LiveUserViewAdapter(context, jointUserList, new AdapterClickListener() {
            @Override
            public void onItemClick(View view, int pos, Object object) {

            }
        });
        binding.liveUserViewRecyclerView.setAdapter(liveUserViewAdapter);
    }

    private void ListenerJoinNode() {
        if (joinValueEventListener == null) {
            joinValueEventListener = new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                    jointUserList.clear();
                    if (dataSnapshot.exists()) {
                        for (DataSnapshot joinSnapsot : dataSnapshot.getChildren()) {
                            Log.d(com.qboxus.tictic.Constants.tag, "Data JSON : " + joinSnapsot.getValue().toString());
                            if (!(TextUtils.isEmpty(joinSnapsot.getValue().toString()))) {
                                StreamJoinModel model = joinSnapsot.getValue(StreamJoinModel.class);
                                jointUserList.add(model);
                            }

                        }
                        liveUserViewAdapter.notifyDataSetChanged();
                        binding.liveUserCount.setText(Functions.getSuffix("" + jointUserList.size()));
                    } else {
                        liveUserViewAdapter.notifyDataSetChanged();
                        binding.liveUserCount.setText(Functions.getSuffix("" + jointUserList.size()));
                    }
                }

                @Override
                public void onCancelled(@NonNull DatabaseError databaseError) {
                    liveUserViewAdapter.notifyDataSetChanged();
                    binding.liveUserCount.setText(Functions.getSuffix("" + jointUserList.size()));
                }
            };
            rootref.child("LiveStreamingUsers").child(streamingId).child("JoinStream")
                    .addValueEventListener(joinValueEventListener);
        }
    }

    public void removeJoinListener() {
        if (rootref != null && joinValueEventListener != null) {
            rootref.child("LiveStreamingUsers").child(streamingId).child("JoinStream").removeEventListener(joinValueEventListener);
            joinValueEventListener = null;
        }
    }

    private void addLikeStream() {
        if (likeValueEventListener == null) {

            likeValueEventListener = new ChildEventListener() {
                @Override
                public void onChildAdded(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
                    if (snapshot.exists()) {
                        StreamShowHeartModel likeData = snapshot.getValue(StreamShowHeartModel.class);
                        SingleCastStreamer.this.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                heartCounter = heartCounter + 1;
                                binding.tvOtherUserLikes.setText(Functions.getSuffix("" + heartCounter) + " " + context.getString(R.string.likes));
                                //heartsShow();
                            }
                        });
                    }
                }

                @Override
                public void onChildChanged(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {

                }

                @Override
                public void onChildRemoved(@NonNull DataSnapshot snapshot) {

                }

                @Override
                public void onChildMoved(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {

                }

                @Override
                public void onCancelled(@NonNull DatabaseError error) {

                }
            };
            rootref.child("LiveStreamingUsers").child(streamingId).child("LikesStream").addChildEventListener(likeValueEventListener);

        }
    }

    private void addStreamInternetConnection() {
        if (connectCheckListener == null) {
            connectedRef = FirebaseDatabase.getInstance().getReference(".info/connected");

            connectCheckListener = new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot snapshot) {
                    boolean connected = snapshot.getValue(Boolean.class);
                    if (connected) {
                        Log.d(com.qboxus.tictic.Constants.tag, "connected");
                        timer.cancel();
                    } else {
                        Log.d(com.qboxus.tictic.Constants.tag, "not connected");
                        timer.cancel();
                        timer = new Timer();
                        timer.schedule(
                                new TimerTask() {
                                    @Override
                                    public void run() {
                                        runOnUiThread(new Runnable() {
                                            @Override
                                            public void run() {
                                                onBackPressed();
                                            }
                                        });
                                    }
                                },
                                DELAY
                        );

                    }
                }

                @Override
                public void onCancelled(@NonNull DatabaseError error) {
                    Log.w(com.qboxus.tictic.Constants.tag, "Listener was cancelled");
                }
            };
            connectedRef.addValueEventListener(connectCheckListener);
        }

    }

    public void removeStreamInternetConnection() {
        if (connectedRef != null && connectCheckListener != null) {
            connectedRef.removeEventListener(connectCheckListener);
        }
    }

    private void ListenerCoinNode() {
        coinValueEventListener = new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                senderCoinsList.clear();
                if (dataSnapshot.exists()) {
                    for (DataSnapshot joinSnapsot : dataSnapshot.getChildren()) {
                        if (!(TextUtils.isEmpty(joinSnapsot.getValue().toString()))) {
                            LiveCoinsModel model = joinSnapsot.getValue(LiveCoinsModel.class);
                            senderCoinsList.add(model);
                        }
                    }
                    double maxCoins = 0;
                    LiveCoinsModel highCoinSender = null;
                    if (senderCoinsList.size() > 0) {
                        binding.tabCoinSender.setVisibility(View.VISIBLE);
                        maxCoins = Double.valueOf(senderCoinsList.get(0).getSendedCoins());
                        highCoinSender = senderCoinsList.get(0);
                    } else {
                        binding.tabCoinSender.setVisibility(View.GONE);
                    }
                    for (LiveCoinsModel item : senderCoinsList) {
                        if (Double.valueOf(item.getSendedCoins()) > maxCoins) {
                            maxCoins = Double.valueOf(item.getSendedCoins());
                            highCoinSender = item;
                        }
                    }
                    if (highCoinSender != null) {
                        binding.tvSender.setText(highCoinSender.getUserName());
                        binding.ivSender.setController(Functions.frescoImageLoad(highCoinSender.getUserPic(), binding.ivSender, false));
                    }


                }

            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        };
        rootref.child("LiveStreamingUsers").child(streamingId).child("CoinsStream").addValueEventListener(coinValueEventListener);
    }

    public void removeCoinListener() {
        if (rootref != null && coinValueEventListener != null) {
            rootref.child("LiveStreamingUsers").child(streamingId).child("CoinsStream").removeEventListener(coinValueEventListener);
        }
    }

    // initialize the views of activity
    private void initUI() {
        boolean isBroadcaster = (userRole == Constants.CLIENT_ROLE_BROADCASTER);


        isAudioActivated = !isBroadcaster;
        isVideoActivated = !isBroadcaster;
        isbeautyActivated = false;
        rtcEngine().setBeautyEffectOptions(isbeautyActivated,
                com.qboxus.tictic.activitesfragments.livestreaming.Constants.DEFAULT_BEAUTY_OPTIONS);

        mVideoGridContainer = findViewById(R.id.live_video_grid_layout);
        mVideoGridContainer.setStatsManager(statsManager());

        rtcEngine().setClientRole(userRole);
        if (isBroadcaster) startBroadcast();
    }

    private void initData() {
        Functions.printLog(com.qboxus.tictic.Constants.tag, "initData");
        mVideoDimension = com.qboxus.tictic.activitesfragments.livestreaming.Constants.VIDEO_DIMENSIONS[
                config().getVideoDimenIndex()];
    }

    private void startBroadcast() {
        rtcEngine().setClientRole(Constants.CLIENT_ROLE_BROADCASTER);
        SurfaceView surface = prepareRtcVideo(Integer.parseInt(config().getUid()), true);
        mVideoGridContainer.addUserVideoSurface(Integer.parseInt(config().getUid()), surface, true);
    }

    private void stopBroadcast() {
        rtcEngine().setClientRole(Constants.CLIENT_ROLE_AUDIENCE);
        removeRtcVideo(Integer.parseInt(config().getUid()), true);
        mVideoGridContainer.removeUserVideo(Integer.parseInt(config().getUid()), true);
    }

    @Override
    public void onJoinChannelSuccess(String channel, int uid, int elapsed) {
        // Do nothing at the moment
    }

    @Override
    public void onUserJoined(int uid, int elapsed) {
        // Do nothing at the moment
    }

    @Override
    public void onUserOffline(final int uid, int reason) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                removeRemoteUser(uid);
            }
        });
    }

    @Override
    public void onFirstRemoteVideoDecoded(final int uid, int width, int height, int elapsed) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Functions.printLog(com.qboxus.tictic.Constants.tag, "onFirstRemoteVideoDecoded");
                renderRemoteUser(uid);
            }
        });
    }

    private void renderRemoteUser(int uid) {
        Functions.printLog(com.qboxus.tictic.Constants.tag, "renderRemoteUser");
        SurfaceView surface = prepareRtcVideo(uid, false);
        mVideoGridContainer.addUserVideoSurface(uid, surface, false);
    }

    private void removeRemoteUser(int uid) {
        removeRtcVideo(uid, false);
        mVideoGridContainer.removeUserVideo(uid, false);
    }

    @Override
    public void onLocalVideoStats(IRtcEngineEventHandler.LocalVideoStats stats) {
        if (!statsManager().isEnabled()) return;

        LocalStatsData data = (LocalStatsData) statsManager().getStatsData(Integer.parseInt(config().getUid()));
        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(Integer.parseInt(config().getUid()));
        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);
    }

    // check the network quality
    @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) {
        Functions.printLog(com.qboxus.tictic.Constants.tag, "onRemoteAudioStats");
        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));
    }

    @Override
    public void finish() {
        super.finish();
        statsManager().clearAllData();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (userRole == Constants.CLIENT_ROLE_BROADCASTER) {
            broadcastRemoveListener();
            removeNode();
            removeNodeCameraRequest();
        }
        removeCoinListener();
        removeLikeStream();
        removeJoinListener();
        removeCommentListener();
        removeProductListener();
        removeStreamInternetConnection();

    }

    public void removeLikeStream() {
        if (rootref != null && likeValueEventListener != null) {
            rootref.child("LiveStreamingUsers").child(streamingId).child("LikesStream").removeEventListener(likeValueEventListener);
            likeValueEventListener = null;
        }


    }

    public void addFirebaseNode() {

        try {
            LiveUserModel model = new LiveUserModel();
            model.setStreamingId(streamingId);
            model.setUserId(userId);
            model.setUserName(userName);
            model.setUserPicture(userPicture);
            model.setOnlineType(onlineType);
            model.setDescription(description);
            model.setSecureCode(secureCode);
            model.setJoinStreamPrice("" + joinStreamPrice);
            model.isDualStreaming = dualStreaming;
            model.isStreamJoinAllow = false;
            model.setUserCoins(Functions.getSharedPreference(context).getString(Variables.U_WALLET, "0"));
            model.setIsVerified(Functions.getSharedPreference(context).getInt(Variables.IS_VERIFIED, 0));
            model.setDuetConnectedUserId("");
            rootref.child("LiveStreamingUsers").child(streamingId).setValue(model);
        } catch (Exception e){}
    }

    // when user goes to offline then change the value status on firebase
    public void removeNode() {
        rootref.child("LiveStreamingUsers").child(streamingId).removeValue();
    }

    public void broadcasterlistenerNode() {

        broadcastValueEventListener = new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                SingleCastStreamer.this.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if (dataSnapshot.exists()) {
                            streamerLiveModel = dataSnapshot.getValue(LiveUserModel.class);

                            binding.tvCoinCount.setText(streamerLiveModel.getUserCoins());

                            Functions.getSharedPreference(context).edit()
                                    .putString(Variables.U_WALLET, streamerLiveModel.getUserCoins()).commit();
                        } else {
                            Toast.makeText(context, context.getString(R.string.your_live_channel_is_close), Toast.LENGTH_SHORT).show();
                            onBackPressed();
                        }

                    }
                });
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        };
        rootref.child("LiveStreamingUsers").child(streamingId).addValueEventListener(broadcastValueEventListener);
    }

    public void broadcastRemoveListener() {
        if (rootref != null && broadcastValueEventListener != null) {
            rootref.child("LiveStreamingUsers").child(streamingId).removeEventListener(broadcastValueEventListener);
        }
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {

            case R.id.tabMenu: {
                ShowDailogForJoinBroadcast();
            }
            break;
            case R.id.tabEffects: {
                performBeautify();
            }
            break;
            case R.id.ivVideoRequest: {
                showCameraRequest();
            }
            break;
            case R.id.tabShareStream: {
                inviteFriendsForStream();
            }
            break;
            case R.id.cross_btn: {
                onBackPressed();
            }
            break;
            case R.id.tvMessage: {
                sendComment();
            }
            break;
            case R.id.tabLikeStreaming: {

            }
            break;
        }
    }

    private void sendComment() {
        EditTextSheetFragment fragment = new EditTextSheetFragment("OwnComment", taggedUserList, new FragmentCallBack() {
            @Override
            public void onResponce(Bundle bundle) {
                if (bundle.getBoolean("isShow", false)) {
                    if (bundle.getString("action").equals("sendComment")) {
                        taggedUserList = (ArrayList<UserModel>) bundle.getSerializable("taggedUserList");
                        String message = bundle.getString("message");
                        binding.tvMessage.setText(message);
                        addMessages("comment");
                    }
                }
            }
        });
        Bundle bundle = new Bundle();
        bundle.putString("replyStr", "");
        fragment.setArguments(bundle);
        fragment.show(getSupportFragmentManager(), "EditTextSheetF");
    }

    private void inviteFriendsForStream() {
        InviteContactsToStreamFragment f = new InviteContactsToStreamFragment(streamingId, "single", new FragmentCallBack() {
            @Override
            public void onResponce(Bundle bundle) {
                if (bundle.getBoolean("isShow", false)) {

                }
            }
        });
        f.show(getSupportFragmentManager(), "InviteContactsToStreamF");
    }

    private void showCameraRequest() {
        final Dialog alertDialog = new Dialog(context);
        alertDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        alertDialog.setContentView(R.layout.camera_request_broadcast_view);
        alertDialog.getWindow().setBackgroundDrawable(ContextCompat.getDrawable(context, R.drawable.d_round_white_background));

        RelativeLayout tabAccept = alertDialog.findViewById(R.id.tabAccept);
        RelativeLayout tabReject = alertDialog.findViewById(R.id.tabReject);
        ImageView closeBtn = alertDialog.findViewById(R.id.closeBtn);


        closeBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                alertDialog.dismiss();
                sendCameraRequest("0");
            }
        });

        tabAccept.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                alertDialog.dismiss();
                sendCameraRequest("2");
            }
        });
        tabReject.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                alertDialog.dismiss();
                sendCameraRequest("0");

            }
        });
        alertDialog.setCancelable(false);
        alertDialog.setCanceledOnTouchOutside(false);
        alertDialog.show();
    }

    private void sendCameraRequest(String type) {
        CameraRequestModel model = new CameraRequestModel();
        model.setRequestState(type);
        rootref.child("LiveStreamingUsers").child(streamingId).child("CameraRequest")
                .setValue(model).addOnCompleteListener(new OnCompleteListener<Void>() {
                    @Override
                    public void onComplete(@NonNull Task<Void> task) {
                        if (task.isComplete()) {
                            Toast.makeText(context, context.getString(R.string.camera_request_sended), Toast.LENGTH_SHORT).show();
                        }
                    }
                });


    }

    public void ShowDailogForJoinBroadcast() {
        final Dialog alertDialog = new Dialog(context);
        alertDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        alertDialog.setContentView(R.layout.live_join_broadcast_view);
        alertDialog.getWindow().setBackgroundDrawable(ContextCompat.getDrawable(context, R.drawable.d_round_white_background));

        ImageView swith_camera_btn = alertDialog.findViewById(R.id.swith_camera_btn);
        ImageView live_btn_mute_audio = alertDialog.findViewById(R.id.live_btn_mute_audio);
        ImageView live_btn_beautification = alertDialog.findViewById(R.id.live_btn_beautification);
        ImageView live_btn_mute_video = alertDialog.findViewById(R.id.live_btn_mute_video);
        RelativeLayout tab_cancel = alertDialog.findViewById(R.id.tab_cancel);
        ImageView closeBtn = alertDialog.findViewById(R.id.closeBtn);
        LinearLayout tabClient = alertDialog.findViewById(R.id.tabClient);
        LinearLayout tabSwitch = alertDialog.findViewById(R.id.tabSwitch);

        if (!(onlineType.equals("oneTwoOne"))) {
            if (userRole != Constants.CLIENT_ROLE_BROADCASTER) {
                tabClient.setVisibility(View.GONE);
                tabSwitch.setVisibility(View.GONE);
            }
        }

        closeBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                alertDialog.dismiss();
            }
        });

        live_btn_mute_audio.setActivated(!isAudioActivated);
        live_btn_mute_video.setActivated(!isVideoActivated);
        live_btn_beautification.setActivated(!isbeautyActivated);

        rtcEngine().setBeautyEffectOptions(live_btn_mute_video.isActivated(),
                com.qboxus.tictic.activitesfragments.livestreaming.Constants.DEFAULT_BEAUTY_OPTIONS);

        tab_cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                alertDialog.dismiss();
                onBackPressed();
            }
        });
        swith_camera_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                alertDialog.dismiss();
                rtcEngine().switchCamera();
            }
        });
        live_btn_mute_audio.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                alertDialog.dismiss();
                isAudioActivated = live_btn_mute_video.isActivated();
                if (!isAudioActivated) return;
                rtcEngine().muteLocalAudioStream(isAudioActivated);
                view.setActivated(!isAudioActivated);
            }
        });
        live_btn_beautification.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                alertDialog.dismiss();
                isbeautyActivated = view.isActivated();
                view.setActivated(!isbeautyActivated);
                performBeautify();
            }
        });
        live_btn_mute_video.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                alertDialog.dismiss();
                isVideoActivated = view.isActivated();
                if (isVideoActivated) {
                    stopBroadcast();
                } else {
                    startBroadcast();
                }
                view.setActivated(!isVideoActivated);
            }
        });
        alertDialog.show();
    }

    private void performBeautify() {
        isbeautyActivated = !isbeautyActivated;
        rtcEngine().setBeautyEffectOptions(isbeautyActivated,
                com.qboxus.tictic.activitesfragments.livestreaming.Constants.DEFAULT_BEAUTY_OPTIONS);
    }

    public void ShowGiftAnimation(LiveCommentModel item) {
        ivGiftProfile = findViewById(R.id.ivGiftProfile);
        tabGiftTitle = findViewById(R.id.tabGiftTitle);
        tabGiftMain = findViewById(R.id.tabGiftMain);
        animationResetAnimation = findViewById(R.id.animationResetAnimation);
        tvGiftTitle = findViewById(R.id.tvGiftTitle);
        tvGiftCountTitle = findViewById(R.id.tvGiftCountTitle);
        ivGiftItem = findViewById(R.id.ivGiftItem);
        tvSendGiftCount = findViewById(R.id.tvSendGiftCount);
        animationGiftCapture = findViewById(R.id.animationGiftCapture);

        String[] str = item.getComment().split("=====");

        Uri imageUri = Uri.parse(str[2]);

        ivGiftProfile.setController(Functions.frescoImageLoad(item.getUserPicture(), ivGiftProfile, false));

        ivGiftItem.setController(Functions.frescoImageLoad("" + imageUri, ivGiftItem, false));
        tvGiftTitle.setText(item.getUserName());
        tvGiftCountTitle.setText(getString(R.string.gave_you_a) + " " + str[1]);
        tvSendGiftCount.setText("X " + str[0]);

        tabGiftMain.animate().alpha(1).translationX(animationGiftCapture.getX()).setDuration(3000).setListener(
                new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        tabGiftMain.animate().translationY(binding.animationCapture.getY()).setDuration(1000).setListener(new AnimatorListenerAdapter() {
                            @Override
                            public void onAnimationEnd(Animator animation) {
                                super.onAnimationEnd(animation);
                                tabGiftMain.clearAnimation();
                                tabGiftMain.animate().alpha(0).translationY(animationResetAnimation.getY()).translationX(animationResetAnimation.getX()).setListener(new AnimatorListenerAdapter() {
                                    @Override
                                    public void onAnimationEnd(Animator animation) {
                                        super.onAnimationEnd(animation);
                                        tabGiftMain.clearAnimation();
                                    }
                                }).start();
                            }
                        }).start();
                    }


                    @Override
                    public void onAnimationStart(Animator animation) {
                        super.onAnimationStart(animation);
                        PlayGiftSound();
                    }
                }).start();
    }

    private void PlayGiftSound() {
        handler = new Handler(Looper.getMainLooper());
        player = MediaPlayer.create(getApplicationContext(), R.raw.gift_tone);
        player.setAudioStreamType(AudioManager.STREAM_MUSIC);
        player.setVolume(100, 100);
        player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                mp.start();
            }
        });
        handler.postDelayed(runnable, 2000);
    }

    public void onTuneStop() {
        if (player != null && player.isPlaying()) {
            player.stop();
        }
        if (handler != null) {
            handler.removeCallbacks(runnable);
        }
    }

    // send the comment to the live user
    public void addMessages(String type) {

        final String key = rootref.child("LiveStreamingUsers").child(streamingId).child("Chat").push().getKey();
        String my_id = Functions.getSharedPreference(this).getString(Variables.U_ID, "");
        String my_name = Functions.getSharedPreference(this).getString(Variables.U_NAME, "");
        String my_image = Functions.getSharedPreference(this).getString(Variables.U_PIC, "");

        Date c = Calendar.getInstance().getTime();
        final String formattedDate = Variables.df.format(c);

        LiveCommentModel commentItem = new LiveCommentModel();
        commentItem.setKey(key);
        commentItem.setUserId(my_id);
        commentItem.setUserName(my_name);
        commentItem.setUserPicture(my_image);
        commentItem.setComment(binding.tvMessage.getText().toString());
        commentItem.setType(type);
        commentItem.setCommentTime(formattedDate);
        rootref.child("LiveStreamingUsers").child(streamingId).child("Chat").child(key).setValue(commentItem);

        binding.tvMessage.setText(context.getString(R.string.add_a_comment));

    }

    // send the comment to the live user
    public void addLikeComment(String type) {

        final String key = rootref.child("LiveStreamingUsers").child(streamingId).child("Chat").push().getKey();
        String my_id = Functions.getSharedPreference(this).getString(Variables.U_ID, "");
        String my_name = Functions.getSharedPreference(this).getString(Variables.U_NAME, "");
        String my_image = Functions.getSharedPreference(this).getString(Variables.U_PIC, "");

        Date c = Calendar.getInstance().getTime();
        final String formattedDate = Variables.df.format(c);

        LiveCommentModel commentItem = new LiveCommentModel();
        commentItem.setKey(key);
        commentItem.setUserId(my_id);
        commentItem.setUserName(my_name);
        commentItem.setUserPicture(my_image);
        commentItem.setComment(my_name + " " + getString(R.string.like_this_stream));
        commentItem.setType(type);
        commentItem.setCommentTime(formattedDate);
        rootref.child("LiveStreamingUsers").child(streamingId).child("Chat").child(key).setValue(commentItem);

        binding.tvMessage.setText(context.getString(R.string.add_a_comment));

    }    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            onTuneStop();
        }
    };

    // send the comment to the live user
    public void addGiftComment(String type, String count, StickerModel model) {

        final String key = rootref.child("LiveStreamingUsers").child(streamingId).child("Chat").push().getKey();
        String my_id = Functions.getSharedPreference(this).getString(Variables.U_ID, "");
        String my_name = Functions.getSharedPreference(this).getString(Variables.U_NAME, "");
        String my_image = Functions.getSharedPreference(this).getString(Variables.U_PIC, "");

        Date c = Calendar.getInstance().getTime();
        final String formattedDate = Variables.df.format(c);

        LiveCommentModel commentItem = new LiveCommentModel();
        commentItem.setKey(key);
        commentItem.setUserId(my_id);
        commentItem.setUserName(my_name);
        commentItem.setUserPicture(my_image);
        commentItem.setComment(count + "=====" + model.name + "=====" + model.image);
        commentItem.setType(type);
        commentItem.setCommentTime(formattedDate);
        commentItem.setSound(model.sound);
        rootref.child("LiveStreamingUsers").child(streamingId).child("Chat").child(key).setValue(commentItem);
        LiveCoinsModel coinsModel = new LiveCoinsModel();
        coinsModel.setUserId(my_id);
        coinsModel.setUserName(my_name);
        coinsModel.setUserPic(my_image);
        coinsModel.setSendedCoins("" + (Double.valueOf(count) * Double.valueOf(model.coins)));
        rootref.child("LiveStreamingUsers").child(streamingId).child("CoinsStream").child(my_id).addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                if (snapshot.exists()) {
                    LiveCoinsModel preModel = snapshot.getValue(LiveCoinsModel.class);
                    double totalCoins = Double.valueOf(preModel.getSendedCoins());
                    totalCoins = totalCoins + ((Double.valueOf(count) * Double.valueOf(model.coins)));

                    HashMap<String, Object> updateMap = new HashMap<>();
                    updateMap.put("sendedCoins", "" + totalCoins);

                    rootref.child("LiveStreamingUsers").child(streamingId).child("CoinsStream").child(my_id).updateChildren(updateMap);
                } else {
                    rootref.child("LiveStreamingUsers").child(streamingId).child("CoinsStream").child(my_id).setValue(coinsModel);
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {

            }
        });

        binding.tvMessage.setText(context.getString(R.string.add_a_comment));

    }

    @SuppressLint("MissingSuperCall")
    @Override
    public void onBackPressed() {
        finish();
    }

    // send notification to all of it follower when user live
    public void sendLiveNotification() {
        JSONObject params = new JSONObject();
        try {
            params.put("user_id", Functions.getSharedPreference(this).getString(Variables.U_ID, ""));
        } catch (Exception e) {
            e.printStackTrace();
        }

        VolleyRequest.JsonPostRequest(SingleCastStreamer.this, ApiLinks.sendLiveStreamPushNotfication, params, Functions.getHeaders(context), new Callback() {
            @Override
            public void onResponce(String resp) {
            }
        });
    }

    private void addNodeCameraRequest() {
        if (cameraRequestEventListener == null) {
            cameraRequestEventListener = new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot snapshot) {
                    if (snapshot.exists()) {
                        CameraRequestModel model = snapshot.getValue(CameraRequestModel.class);
                        if (model.getRequestState().equals("1")) {
                            binding.ivVideoRequest.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_camera_request_r));
                            binding.ivVideoRequest.setVisibility(View.VISIBLE);
                            showCameraRequest();
                        } else if (model.getRequestState().equals("2")) {
                            binding.ivVideoRequest.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_camera_request_a));
                            binding.ivVideoRequest.setVisibility(View.VISIBLE);
                        } else {
                            binding.ivVideoRequest.setVisibility(View.GONE);
                        }
                    }
                }

                @Override
                public void onCancelled(@NonNull DatabaseError error) {

                }
            };
            rootref.child("LiveStreamingUsers").child(streamingId).child("CameraRequest").addValueEventListener(cameraRequestEventListener);

        }
    }

    private void removeNodeCameraRequest() {
        if (rootref != null && cameraRequestEventListener != null) {
            rootref.child("LiveStreamingUsers").child(streamingId).child("CameraRequest").removeEventListener(cameraRequestEventListener);
            cameraRequestEventListener = null;
        }
    }




}
