package com.nutomic.syncthingandroid.activities;

import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;

import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.service.RestApi;
import com.nutomic.syncthingandroid.service.SyncthingService;
import com.nutomic.syncthingandroid.service.SyncthingServiceBinder;

import java.util.LinkedList;

/**
 * Connects to {@link SyncthingService} and provides access to it.
 */
public abstract class SyncthingActivity extends ToolbarBindingActivity implements ServiceConnection {

    public static final String EXTRA_FIRST_START = "com.nutomic.syncthing-android.SyncthingActivity.FIRST_START";

    private SyncthingService mSyncthingService;
    private AlertDialog mLoadingDialog;

    private final LinkedList<OnServiceConnectedListener> mServiceConnectedListeners = new LinkedList<>();

    /**
     * To be used for Fragments.
     */
    public interface OnServiceConnectedListener {
        void onServiceConnected();
    }

    @Override
    protected void onPause() {
        unbindService(this);
        super.onPause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        bindService(new Intent(this, SyncthingService.class), this, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        dismissLoadingDialog();
        if (getService() != null) {
            getService().unregisterOnApiChangeListener(this::onApiChange);
        }
    }

    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        SyncthingServiceBinder binder = (SyncthingServiceBinder) iBinder;
        mSyncthingService = binder.getService();
        mSyncthingService.registerOnApiChangeListener(this::onApiChange);
        for (OnServiceConnectedListener listener : mServiceConnectedListeners) {
            listener.onServiceConnected();
        }
        mServiceConnectedListeners.clear();
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {
        mSyncthingService = null;
    }

    private void onApiChange(SyncthingService.State currentState) {
        switch (currentState) {
            case INIT: // fallthrough
            case STARTING:
                showLoadingDialog();
                break;
            case ACTIVE: // fallthrough
            case DISABLED:
                dismissLoadingDialog();
                break;
        }
    }

    /**
     * Used for Fragments to use the Activity's service connection.
     */
    public void registerOnServiceConnectedListener(OnServiceConnectedListener listener) {
        if (mSyncthingService != null) {
            listener.onServiceConnected();
        } else {
            mServiceConnectedListeners.addLast(listener);
        }
    }

    /**
     * Returns service object (or null if not bound).
     */
    public SyncthingService getService() {
        return mSyncthingService;
    }

    /**
     * Returns RestApi instance, or null if SyncthingService is not yet connected.
     */
    public RestApi getApi() {
        return (getService() != null)
                ? getService().getApi()
                : null;
    }

    /**
     * Shows the loading dialog with the correct text ("creating keys" or "loading").
     */
    private void showLoadingDialog() {
        if (isFinishing() || mLoadingDialog != null)
            return;

        // Try to fix WindowManager$BadTokenException crashes on Android 7.
        // https://stackoverflow.com/q/46030692/1837158
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            ActivityManager.RunningAppProcessInfo myProcess = new ActivityManager.RunningAppProcessInfo();
            ActivityManager.getMyMemoryState(myProcess);
            boolean isInBackground =
                    myProcess.importance != ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
            if (isInBackground)
                return;
        }

        LayoutInflater inflater = getLayoutInflater();
        @SuppressLint("InflateParams")
        View dialogLayout = inflater.inflate(R.layout.dialog_loading, null);
        TextView loadingText = (TextView) dialogLayout.findViewById(R.id.loading_text);
        loadingText.setText((getIntent().getBooleanExtra(EXTRA_FIRST_START, false))
                ? R.string.web_gui_creating_key
                : R.string.api_loading);

        mLoadingDialog = new AlertDialog.Builder(this)
                .setCancelable(false)
                .setView(dialogLayout)
                .show();
    }

    private void dismissLoadingDialog() {
        if (mLoadingDialog != null && mLoadingDialog.isShowing()) {
            mLoadingDialog.dismiss();
            mLoadingDialog = null;
        }
    }

}

@@ -87,44 +87,8 @@
 nt;%0A
-import android.app.ActivityManager;%0A
 impo
@@ -276,21 +276,23 @@
 roid.os.
-Build
+IBinder
 ;%0Aimport
@@ -304,44 +304,16 @@
 oid.
-os.Bundle;%0Aimport android.os.IBinder
+util.Log
 ;%0Aim
@@ -836,16 +836,76 @@
 tion %7B%0A%0A
+    private static final String TAG = %22SyncthingActivity%22;%0A%0A
     publ
@@ -3798,584 +3798,8 @@
 n;%0A%0A
-        // Try to fix WindowManager$BadTokenException crashes on Android 7.%0A        // https://stackoverflow.com/q/46030692/1837158%0A        if (Build.VERSION.SDK_INT %3E= Build.VERSION_CODES.JELLY_BEAN) %7B%0A            ActivityManager.RunningAppProcessInfo myProcess = new ActivityManager.RunningAppProcessInfo();%0A            ActivityManager.getMyMemoryState(myProcess);%0A            boolean isInBackground =%0A                    myProcess.importance != ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;%0A            if (isInBackground)%0A                return;%0A        %7D%0A%0A
     
@@ -3845,24 +3845,24 @@
 Inflater();%0A
+
         @Sup
@@ -4223,24 +4223,42 @@
 _loading);%0A%0A
+        try %7B%0A    
         mLoa
@@ -4312,24 +4312,28 @@
             
+    
 .setCancelab
@@ -4342,16 +4342,20 @@
 (false)%0A
+    
         
@@ -4401,16 +4401,20 @@
         
+    
 .show();
@@ -4410,24 +4410,197 @@
    .show();%0A
+        %7D catch (RuntimeException e) %7B%0A            // Catch and do nothing, workaround for https://stackoverflow.com/q/46030692/1837158%0A            Log.w(TAG, e);%0A        %7D%0A
     %7D%0A%0A    p

Add workaround for AlertDialog crash