package com.example.doctor_app_flutter.ui;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.example.doctor_app_flutter.Model.GetSessionStatusModel;
import com.example.doctor_app_flutter.Model.SessionStatusModel;
import com.example.doctor_app_flutter.R;
import com.opentok.android.Session;
import com.opentok.android.Stream;
import com.opentok.android.Publisher;
import com.opentok.android.PublisherKit;
import com.opentok.android.Subscriber;
import com.opentok.android.BaseVideoRenderer;
import com.opentok.android.OpentokError;
import com.opentok.android.SubscriberKit;

import java.util.List;
import java.util.Objects;

import pub.devrel.easypermissions.AfterPermissionGranted;
import pub.devrel.easypermissions.AppSettingsDialog;
import pub.devrel.easypermissions.EasyPermissions;

public class VideoCallActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks,
        Session.SessionListener,
        Publisher.PublisherListener,
        Subscriber.VideoListener, VideoCallContract.VideoCallView {

    private static final String TAG = VideoCallActivity.class.getSimpleName();

    VideoCallContract.VideoCallPresenter videoCallPresenter;

    private static final int RC_SETTINGS_SCREEN_PERM = 123;
    private static final int RC_VIDEO_APP_PERM = 124;


    private Session mSession;
    private Publisher mPublisher;
    private Subscriber mSubscriber;

    private Handler mVolHandler, mConnectedHandler;
    private Runnable mVolRunnable, mConnectedRunnable;

    private FrameLayout mPublisherViewContainer;
    private RelativeLayout mSubscriberViewContainer;
    private RelativeLayout controlPanel;

    private String apiKey;
    private String sessionId;
    private String token;
    private String appLang;
    private String baseUrl;

    private boolean isSwitchCameraClicked;
    private boolean isCameraClicked;
    private boolean isSpeckerClicked;
    private boolean isMicClicked;

    private ImageView mCallBtn;
    private ImageView mCameraBtn;
    private ImageView mSwitchCameraBtn;
    private ImageView mspeckerBtn;
    private ImageView mMicBtn;

    private ProgressBar progressBar;
    private CountDownTimer countDownTimer;
    private TextView progressBarTextView;
    private RelativeLayout progressBarLayout;

    private boolean isConnected = false;

    private GetSessionStatusModel sessionStatusModel;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setTheme(R.style.AppTheme);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_video_call);
        Objects.requireNonNull(getSupportActionBar()).hide();
        initUI();
        requestPermissions();
    }

    @Override
    protected void onPause() {
        super.onPause();

        if (mSession == null) {
            return;
        }
        mSession.onPause();

        if (isFinishing()) {
            disconnectSession();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        if (mSession == null) {
            return;
        }
        mSession.onResume();
    }

    @Override
    protected void onDestroy() {
        disconnectSession();

        super.onDestroy();
    }

    @SuppressLint("ClickableViewAccessibility")
    private void initUI() {
        mPublisherViewContainer = (FrameLayout) findViewById(R.id.local_video_view_container);
        mSubscriberViewContainer = (RelativeLayout) findViewById(R.id.remote_video_view_container);

        apiKey = getIntent().getStringExtra("apiKey");
        sessionId = getIntent().getStringExtra("sessionId");
        token = getIntent().getStringExtra("token");
        appLang = getIntent().getStringExtra("appLang");
        baseUrl = getIntent().getStringExtra("baseUrl");
        sessionStatusModel = getIntent().getParcelableExtra("sessionStatusModel");

        controlPanel = findViewById(R.id.control_panel);

        videoCallPresenter = new VideoCallPresenterImpl(this, baseUrl);


        mCallBtn = findViewById(R.id.btn_call);
        mCameraBtn = findViewById(R.id.btn_camera);
        mSwitchCameraBtn = findViewById(R.id.btn_switch_camera);
        mspeckerBtn = findViewById(R.id.btn_specker);
        mMicBtn = findViewById(R.id.btn_mic);

        //  progressBarLayout=findViewById(R.id.progressBar);
        //   progressBar=findViewById(R.id.progress_bar);
//        progressBarTextView=findViewById(R.id.progress_bar_text);
//        progressBar.setVisibility(View.GONE);

        hiddenButtons();

        checkClientConnected();

        mSubscriberViewContainer.setOnTouchListener((v, event) -> {
            controlPanel.setVisibility(View.VISIBLE);
            mVolHandler.removeCallbacks(mVolRunnable);
            mVolHandler.postDelayed(mVolRunnable, 5 * 1000);
            return true;
        });

        if (appLang.equals("ar")) {
            progressBarLayout.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
        }

    }

    private void checkClientConnected() {
        mConnectedHandler = new Handler();
        mConnectedRunnable = () -> {
            if (!isConnected) {
                videoCallPresenter.callClintConnected(sessionStatusModel);
            }
        };
        mConnectedHandler.postDelayed(mConnectedRunnable, 30 * 1000);

    }

    private void hiddenButtons() {
        mVolHandler = new Handler();
        mVolRunnable = new Runnable() {
            public void run() {
                controlPanel.setVisibility(View.GONE);
            }
        };
        mVolHandler.postDelayed(mVolRunnable, 5 * 1000);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
    }

    @Override
    public void onPermissionsGranted(int requestCode, List<String> perms) {
        Log.d(TAG, "onPermissionsGranted:" + requestCode + ":" + perms.size());
    }

    @Override
    public void onPermissionsDenied(int requestCode, List<String> perms) {
        Log.d(TAG, "onPermissionsDenied:" + requestCode + ":" + perms.size());

        if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
            new AppSettingsDialog.Builder(this)
                    .setTitle(getString(R.string.title_settings_dialog))
                    .setRationale(getString(R.string.rationale_ask_again))
                    .setPositiveButton(getString(R.string.setting))
                    .setNegativeButton(getString(R.string.cancel))
                    .setRequestCode(RC_SETTINGS_SCREEN_PERM)
                    .build()
                    .show();
        }
    }

    @AfterPermissionGranted(RC_VIDEO_APP_PERM)
    private void requestPermissions() {
        String[] perms = {Manifest.permission.INTERNET, Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO};
        if (EasyPermissions.hasPermissions(this, perms)) {
            mSession = new Session.Builder(VideoCallActivity.this, apiKey, sessionId).build();
            mSession.setSessionListener(this);
            mSession.connect(token);
        } else {
            EasyPermissions.requestPermissions(this, getString(R.string.remaining_ar), RC_VIDEO_APP_PERM, perms);
        }
    }

    @Override
    public void onConnected(Session session) {
        Log.i(TAG, "Session Connected");

        mPublisher = new Publisher.Builder(this).build();
        mPublisher.setPublisherListener(this);

        mPublisherViewContainer.addView(mPublisher.getView());

        if (mPublisher.getView() instanceof GLSurfaceView) {
            ((GLSurfaceView) mPublisher.getView()).setZOrderOnTop(true);
        }

        mSession.publish(mPublisher);
    }

    @Override
    public void onDisconnected(Session session) {
        Log.d(TAG, "onDisconnected: disconnected from session " + session.getSessionId());

        mSession = null;
    }

    @Override
    public void onError(Session session, OpentokError opentokError) {
        Log.d(TAG, "onError: Error (" + opentokError.getMessage() + ") in session " + session.getSessionId());

        Toast.makeText(this, "Session error. See the logcat please.", Toast.LENGTH_LONG).show();
        finish();
    }

    @Override
    public void onStreamReceived(Session session, Stream stream) {
        Log.d(TAG, "onStreamReceived: New stream " + stream.getStreamId() + " in session " + session.getSessionId());
        if (mSubscriber != null) {
            isConnected = true;
            return;
        }
        isConnected = true;
        subscribeToStream(stream);
    }

    @Override
    public void onStreamDropped(Session session, Stream stream) {
        Log.d(TAG, "onStreamDropped: Stream " + stream.getStreamId() + " dropped from session " + session.getSessionId());

        if (mSubscriber == null) {
            return;
        }

        if (mSubscriber.getStream().equals(stream)) {
            mSubscriberViewContainer.removeView(mSubscriber.getView());
            mSubscriber.destroy();
            mSubscriber = null;
        }
        disconnectSession();
    }

    @Override
    public void onStreamCreated(PublisherKit publisherKit, Stream stream) {
        Log.d(TAG, "onStreamCreated: Own stream " + stream.getStreamId() + " created");
    }

    @Override
    public void onStreamDestroyed(PublisherKit publisherKit, Stream stream) {
        Log.d(TAG, "onStreamDestroyed: Own stream " + stream.getStreamId() + " destroyed");
    }

    @Override
    public void onError(PublisherKit publisherKit, OpentokError opentokError) {
        Log.d(TAG, "onError: Error (" + opentokError.getMessage() + ") in publisher");

        Toast.makeText(this, "Session error. See the logcat please.", Toast.LENGTH_LONG).show();
        finish();
    }

    @Override
    public void onVideoDataReceived(SubscriberKit subscriberKit) {
        mSubscriber.setStyle(BaseVideoRenderer.STYLE_VIDEO_SCALE, BaseVideoRenderer.STYLE_VIDEO_FILL);
        mSubscriberViewContainer.addView(mSubscriber.getView());
    }

    @Override
    public void onVideoDisabled(SubscriberKit subscriberKit, String s) {

    }

    @Override
    public void onVideoEnabled(SubscriberKit subscriberKit, String s) {

    }

    @Override
    public void onVideoDisableWarning(SubscriberKit subscriberKit) {

    }

    @Override
    public void onVideoDisableWarningLifted(SubscriberKit subscriberKit) {

    }

    private void subscribeToStream(Stream stream) {
        mSubscriber = new Subscriber.Builder(VideoCallActivity.this, stream).build();
        mSubscriber.setVideoListener(this);
        mSession.subscribe(mSubscriber);
    }

    private void disconnectSession() {
        if (mSession == null) {
            setResult(Activity.RESULT_CANCELED);
            finish();
            return;
        }

        if (mSubscriber != null) {
            mSubscriberViewContainer.removeView(mSubscriber.getView());
            mSession.unsubscribe(mSubscriber);
            mSubscriber.destroy();
            mSubscriber = null;
        }

        if (mPublisher != null) {
            mPublisherViewContainer.removeView(mPublisher.getView());
            mSession.unpublish(mPublisher);
            mPublisher.destroy();
            mPublisher = null;
        }
        mSession.disconnect();
        if (countDownTimer != null) {
            countDownTimer.cancel();
        }
        finish();
    }

    public void onSwitchCameraClicked(View view) {
        if (mPublisher != null) {
            isSwitchCameraClicked = !isSwitchCameraClicked;
            mPublisher.cycleCamera();
            int res = isSwitchCameraClicked ? R.drawable.flip_disapled : R.drawable.flip_enabled;
            mSwitchCameraBtn.setImageResource(res);
        }
    }

    public void onCameraClicked(View view) {
        if (mPublisher != null) {
            isCameraClicked = !isCameraClicked;
            mPublisher.setPublishVideo(!isCameraClicked);
            int res = isCameraClicked ? R.drawable.video_disanabled : R.drawable.video_enabled;
            mCameraBtn.setImageResource(res);
        }
    }

    public void onSpeckerClicked(View view) {
        if (mSubscriber != null) {
            isSpeckerClicked = !isSpeckerClicked;
            mSubscriber.setSubscribeToAudio(!isSpeckerClicked);
            int res = isSpeckerClicked ? R.drawable.audio_disabled : R.drawable.audio_enabled;
            mspeckerBtn.setImageResource(res);
        }
    }

    public void onMicClicked(View view) {

        if (mPublisher != null) {
            isMicClicked = !isMicClicked;
            mPublisher.setPublishAudio(!isMicClicked);
            int res = isMicClicked ? R.drawable.mic_disabled : R.drawable.mic_enabled;
            mMicBtn.setImageResource(res);
        }
    }

    public void onCallClicked(View view) {
        disconnectSession();
    }

    @Override
    public void onCallSuccessful(SessionStatusModel sessionStatusModel) {
        if (sessionStatusModel.getSessionStatus() == 2 || sessionStatusModel.getSessionStatus() == 3) {
            Intent returnIntent = new Intent();
            returnIntent.putExtra("sessionStatusNotRespond", sessionStatusModel);
            setResult(Activity.RESULT_OK, returnIntent);
            finish();
        }
    }

    @Override
    public void onFailure() {

    }
}