package org.mapcomplete;

import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.util.Log;
import android.view.Window;
import android.view.WindowInsets;
import android.window.OnBackInvokedDispatcher;

import androidx.activity.EdgeToEdge;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.view.WindowCompat;

import com.getcapacitor.BridgeActivity;
import com.getcapacitor.JSObject;
import com.getcapacitor.PluginCall;
import android.app.Activity;
public class MainActivity extends BridgeActivity {

    private PluginCall locationRequest = null;
    private PluginCall authRequest = null;
    private PluginCall backbutton = null;

    private JSObject loginToken = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        registerPlugin(Databridge.class);
        new GeolocationBridge(getApplicationContext(), this);
        Databridge.addResponder("location:request-permission", pluginCall -> {
            this.locationRequest = pluginCall;
            if(this.hasGeolocationPermission()){
                Databridge.sendAnswerTo(pluginCall, ""+true);
                return;
            }
            this.requestGeolocationPermission();
            // note: this will call back via:
            // this.onRequestPermissionsResult();
        });
        Databridge.addResponder("location:has-permission", pluginCall -> {
            var permission = this.hasGeolocationPermission();
            System.out.println("Android: Geolocation permission is: "+ permission);
            Databridge.sendAnswerTo(pluginCall, "" + permission);
        });
        Databridge.addResponder("open:login", pluginCall -> {
            // We got a request - open the browser on 'app.mapcomplete.org/land' to login in the browser, then pass the token along
            Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://app.mapcomplete.org/land.html"));
            startActivity(browserIntent);
            pluginCall.resolve(); // We simply resolve without anything
        });
        Databridge.addResponder("request:login", pluginCall -> {
            // We got a request - open the browser on 'app.mapcomplete.org/land' to login in the browser, then pass the token along
            this.authRequest = pluginCall;
            if (this.loginToken != null) {
                pluginCall.resolve(this.loginToken);
            }
        });

        Databridge.addResponder("backbutton", responder -> {
            this.backbutton = responder;
            responder.setKeepAlive(true);
        });

        Databridge.addResponder("exit", responder -> {
            Log.i("databridge","got exit request");
            finishAffinity();
        });

        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);

        var useInsets = Build.VERSION.SDK_INT > Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
        Log.i("Insets","Using insets:"+useInsets+", sdk_int:"+Build.VERSION.SDK_INT+" "+Build.VERSION_CODES.UPSIDE_DOWN_CAKE);
        WindowCompat.setDecorFitsSystemWindows(getWindow(), !useInsets);
        if(useInsets) {
            Databridge.addResponder("insets", (responder) -> {
                var view = getWindow().getDecorView();
                var insets = view.getRootWindowInsets();
                var topInsetPxSize = insets.getInsetsIgnoringVisibility(WindowInsets.Type.statusBars()).top;
                var bottomInsetPxSize = insets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars()).bottom;

                var json = "{ \"top\": " + topInsetPxSize + ", \"bottom\":" + bottomInsetPxSize + "}";
                Log.i("insets", "Inset sizes are:" + topInsetPxSize + " bottom:" + bottomInsetPxSize);
                Databridge.sendAnswerTo(responder, json);
            });
        }else{
            Log.i("insets","Not enabling insets, version to low");
            Databridge.addResponder("insets", (responder) -> {
                var json = "{ \"top\": 0, \"bottom\": 0}";
                Databridge.sendAnswerTo(responder, json);
            });
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            getOnBackInvokedDispatcher().registerOnBackInvokedCallback(OnBackInvokedDispatcher.PRIORITY_OVERLAY,
                    () -> {
                        System.out.println("Back button pressed");
                        if (this.backbutton != null) {
                            Databridge.sendAnswerTo(this.backbutton, "backbutton pressed");
                        }
                    }
            );
        }
    }

    @Override
    public void onBackPressed() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
            System.out.println("Back button pressed (old)");
            if (this.backbutton != null) {
                Databridge.sendAnswerTo(this.backbutton, "backbutton pressed");
            }
        }else{
            super.onBackPressed();
        }

    }



    private boolean hasGeolocationPermission() {
        return ContextCompat.checkSelfPermission(
                getApplicationContext(),
                android.Manifest.permission.ACCESS_FINE_LOCATION
        ) == PackageManager.PERMISSION_GRANTED;
    }

    private void requestGeolocationPermission() {
        if (this.hasGeolocationPermission()) {
            return;
        }
        // Permission is not granted, request it
        ActivityCompat.requestPermissions(
        this,
        new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
        GeolocationBridge.requestCode
        );
        // The request will call `this.onRequestPermissionsResult` when done!
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        if (!Intent.ACTION_VIEW.equals(intent.getAction())) {
            return;
        }
        Uri url = intent.getData();
        if (url == null) {
            return;
        }

        System.out.println("urlPath: " + url.getPath() + ";" + String.join(", ", url.getQueryParameterNames()));
        if (url.getQueryParameterNames().contains("oauth_token")) {
            var token = url.getQueryParameter("oauth_token");
            JSObject obj = new JSObject();
            obj.put("oauth_token", token);
            JSObject res = new JSObject();
            res.put("value", obj);
            Log.i("main", "Resolving auth call, param is " + token);
            this.loginToken = res;
            if (this.authRequest != null) {
                this.authRequest.resolve(res);
            }
        }

        System.out.println("Intercepted URL: " + url);
    }

    @NonNull
    @Override
    public OnBackInvokedDispatcher getOnBackInvokedDispatcher() {

        return super.getOnBackInvokedDispatcher();
    }


    @Override
    public void onRequestPermissionsResult(
            int requestCode,
            String[] permissions,
            int[] grantResults
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == GeolocationBridge.requestCode) {
            if (this.locationRequest != null && grantResults.length > 0) {
                // We've only requested "FINE_LOCATION"
                var granted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
                Log.i("Geolocation", "Got fine location permission: " + granted);
                Databridge.sendAnswerTo(this.locationRequest, ""+granted);
            }
        }
    }

}
