package com.dyteMobileSdk;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Build;
import android.os.Handler;
import android.os.PowerManager;
import android.util.Log;
import android.view.WindowManager;

import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.modules.core.DeviceEventManagerModule;

import java.io.Serializable;
import java.util.HashMap;

@ReactModule(name="DyteHelperModule")
public class DyteHelperModule extends ReactContextBaseJavaModule {

    private final ReactApplicationContext reactContext;
    private static final String ERROR_INVALID_ACTIVITY = "E_INVALID_ACTIVITY";

    // react-native-background-timer start
    private Handler handler;
    private ReactContext reactContext2;
    private Runnable runnable;
    private PowerManager powerManager;
    private PowerManager.WakeLock wakeLock;
    private int existingOrientation;
    private boolean isForcedLandscapeToggled;
    private final LifecycleEventListener listener = new LifecycleEventListener() {
        @Override
        public void onHostResume() {
        }

        @Override
        public void onHostPause() {
        }

        @Override
        public void onHostDestroy() {
            if (wakeLock.isHeld()) wakeLock.release();
            Intent intent = new Intent(getReactApplicationContext(), ForegroundService.class);
            intent.setAction(Constants.ACTION_FOREGROUND_SERVICE_STOP);
            getReactApplicationContext().stopService(intent);
        }
    };
    //react-native-background-timer end

    private class Request {

        public boolean[] rationaleStatuses;
        public Callback callback;

        public Request(boolean[] rationaleStatuses, Callback callback) {
            this.rationaleStatuses = rationaleStatuses;
            this.callback = callback;
        }
    }

    public DyteHelperModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
        this.powerManager = (PowerManager) getReactApplicationContext().getSystemService(reactContext.POWER_SERVICE);
        this.wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "dytesdk:wakelock");
        reactContext.addLifecycleEventListener(listener);
        this.isForcedLandscapeToggled = false;
    }

    @Override
    public String getName() {
        return "DyteHelper";
    }

    @ReactMethod
    public void createNotificationChannel(Promise promise) {
        NotificationHelper.getInstance(getReactApplicationContext()).createNotificationChannel(promise);
    }

    @ReactMethod
    public void startService(Promise promise) {
        Intent intent = new Intent(getReactApplicationContext(), ForegroundService.class);
        intent.setAction(Constants.ACTION_FOREGROUND_SERVICE_START);
        ComponentName componentName = getReactApplicationContext().startService(intent);
        if (componentName != null) {
            promise.resolve(null);
        } else {
            promise.reject(Constants.ERROR_SERVICE_ERROR, "DyteForegroundService: Foreground service is not started");
        }
    }

    @ReactMethod
    public void stopService(Promise promise) {
        Intent intent = new Intent(getReactApplicationContext(), ForegroundService.class);
        intent.setAction(Constants.ACTION_FOREGROUND_SERVICE_STOP);
        boolean stopped = getReactApplicationContext().stopService(intent);
        if (stopped) {
            promise.resolve(null);
        } else {
            promise.reject(Constants.ERROR_SERVICE_ERROR, "DyteForegroundService: Foreground service failed to stop");
        }
    }

    @ReactMethod
    public void activateScreenWake() {
        final Activity activity = getCurrentActivity();

        if (activity != null) {
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                }
            });
        }
    }

    @ReactMethod
    public void deactivateScreenWake() {
        final Activity activity = getCurrentActivity();

        if (activity != null) {
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                }
            });
        }
    }

    @ReactMethod
    public void forceLandscape() {
        final Activity activity = getCurrentActivity();

        if (activity != null) {
            this.isForcedLandscapeToggled = true;
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    existingOrientation = activity.getRequestedOrientation();
                    activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                }
            });
        }
    }

    @ReactMethod
    public void forcePotrait() {
        final Activity activity = getCurrentActivity();

        if (activity != null) {
            this.isForcedLandscapeToggled = true;
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    existingOrientation = activity.getRequestedOrientation();
                    activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                }
            });
        }
    }


    @ReactMethod
    public void resetOrientation() {
        final Activity activity = getCurrentActivity();

        if (activity != null) {
            this.isForcedLandscapeToggled = false;
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    activity.setRequestedOrientation(existingOrientation);
                }
            });
        }
    }

    @ReactMethod
    public void isForcedLandscape(Promise p) {
        p.resolve(this.isForcedLandscapeToggled);
    }


    @ReactMethod
    public void backgroundTimerStart(final int delay) {
        if (!wakeLock.isHeld()) wakeLock.acquire();

        handler = new Handler();
        runnable = new Runnable() {
            @Override
            public void run() {
                backgroundTimerSendEvent(reactContext, "backgroundTimer");
            }
        };

        handler.post(runnable);
    }

    @ReactMethod
    public void backgroundTimerStop() {
        if (wakeLock.isHeld()) wakeLock.release();

        // avoid null pointer exceptio when stop is called without start
        if (handler != null) handler.removeCallbacks(runnable);
    }

    private void backgroundTimerSendEvent(ReactContext reactContext, String eventName) {
        reactContext
                .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit(eventName, null);
    }

    @ReactMethod
    public void backgroundTimerSetTimeout(final int id, final double timeout) {
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (getReactApplicationContext().hasActiveCatalystInstance()) {
                    getReactApplicationContext()
                            .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                            .emit("backgroundTimer.timeout", id);
                }
            }
        }, (long) timeout);
    }

    @ReactMethod
    public  void SDKSelfBasic(String id, String name, String picture) {
        Intent intent = new Intent("dyte::self::basic");
        intent.putExtra("id", id);
        intent.putExtra("name", name);
        intent.putExtra("picture", picture);
        LocalBroadcastManager.getInstance(getCurrentActivity().getApplicationContext()).sendBroadcast(intent);
    }

    @ReactMethod
    public void SDKSelfAudio(boolean enabled) {
        Intent intent = new Intent("dyte::self::audio");
        intent.putExtra("audioEnabled", enabled);
        LocalBroadcastManager.getInstance(getCurrentActivity().getApplicationContext()).sendBroadcast(intent);
    }

    @ReactMethod
    public void SDKSelfVideo(boolean enabled) {
        Intent intent = new Intent("dyte::self::video");
        intent.putExtra("videoEnabled", enabled);
        LocalBroadcastManager.getInstance(getCurrentActivity().getApplicationContext()).sendBroadcast(intent);
    }

    @ReactMethod
    public void SDKSelfPin(boolean isPinned) {
        Intent intent = new Intent("dyte::self::pin");
        intent.putExtra("isPinned", isPinned);
        LocalBroadcastManager.getInstance(getCurrentActivity().getApplicationContext()).sendBroadcast(intent);
    }

    @ReactMethod
    public void SDKSelfScreenshare(boolean isScreensharing) {
        Intent intent = new Intent("dyte::self::screensharing");
        intent.putExtra("isScreensharing", isScreensharing);
        LocalBroadcastManager.getInstance(getCurrentActivity().getApplicationContext()).sendBroadcast(intent);
    }

    @ReactMethod
    public void SDKMeetingConnect() {
        Intent intent = new Intent("dyte::events::connect");
        LocalBroadcastManager.getInstance(getCurrentActivity().getApplicationContext()).sendBroadcast(intent);
    }

    @ReactMethod
    public void SDKMeetingDisconnect() {
        Intent intent = new Intent("dyte::events::disconnect");
        Log.d("dytesdkhelper","disconnect");
        LocalBroadcastManager.getInstance(getCurrentActivity().getApplicationContext()).sendBroadcast(intent);
    }

    @ReactMethod
    public void SDKMeetingJoined() {
        Intent intent = new Intent("dyte::events::meetingJoined");
        LocalBroadcastManager.getInstance(getCurrentActivity().getApplicationContext()).sendBroadcast(intent);
    }

    @ReactMethod
    public void SDKMeetingEnded() {
        Intent intent = new Intent("dyte::events::meetingEnded");
        Log.d("dytesdkhelper","meetingEnded");
        LocalBroadcastManager.getInstance(getCurrentActivity().getApplicationContext()).sendBroadcast(intent);
    }

    @ReactMethod
    public void SDKActiveSpeaker(String peerId) {
        Intent intent = new Intent("dyte::events::activeSpeaker");
        intent.putExtra("peerId", peerId);
        LocalBroadcastManager.getInstance(getCurrentActivity().getApplicationContext()).sendBroadcast(intent);
    }

    @ReactMethod
    public void SDKParticipantLeave(String peerId) {
        Intent intent = new Intent("dyte::events::participantLeave");
        intent.putExtra("peerId", peerId);
        LocalBroadcastManager.getInstance(getCurrentActivity().getApplicationContext()).sendBroadcast(intent);
    }

    @ReactMethod
    public void SDKParticipantJoin(String id, String name, String picture, String clientSpecificId, Boolean audioEnabled, Boolean videoEnabled, Boolean isPinned, Boolean isScreensharing) {
        Intent intent = new Intent("dyte::events::participantJoin");
        intent.putExtra("id", id);
        intent.putExtra("name", name);
        intent.putExtra("picture", picture);
        intent.putExtra("clientSpecificId", clientSpecificId);
        intent.putExtra("audioEnabled", audioEnabled);
        intent.putExtra("videoEnabled", videoEnabled);
        intent.putExtra("isPinned", isPinned);
        intent.putExtra("isScreensharing", isScreensharing);
        LocalBroadcastManager.getInstance(getCurrentActivity().getApplicationContext()).sendBroadcast(intent);
    }

    @ReactMethod
    public void SDKParticipantUpdate(String id,Boolean audioEnabled, Boolean videoEnabled, Boolean isPinned, Boolean isScreensharing) {
        Intent intent = new Intent("dyte::events::participantUpdate");
        intent.putExtra("id", id);
        intent.putExtra("audioEnabled", audioEnabled);
        intent.putExtra("videoEnabled", videoEnabled);
        intent.putExtra("isPinned", isPinned);
        intent.putExtra("isScreensharing", isScreensharing);
        LocalBroadcastManager.getInstance(getCurrentActivity().getApplicationContext()).sendBroadcast(intent);
    }

    @ReactMethod
    public void SDKMessage(ReadableMap message) {

    }

    @ReactMethod
    public void SDKRoomMessage(ReadableMap message) {

    }
}