package com.secureline.protect;

import android.app.Activity;
import android.app.AlertDialog;
import android.os.Bundle;
import android.content.Intent;
import android.net.Uri;
import android.os.IBinder;
import android.os.ServiceManager;
import android.text.InputType;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.android.secureline.ISecureLineManager;
import com.secureline.ui.SecureLineHeroView;
import com.secureline.ui.SecureLineStatusBadge;
import com.secureline.ui.SecureLineTimelineView;

public final class ProtectionDetailsActivity extends Activity {
    public static final String EXTRA_PROTECTION_KEY = "protection_key";
    public static final String KEY_REMOTE="remote", KEY_USB="usb", KEY_PANIC="panic", KEY_CALL="call",
            KEY_MESSAGE="message", KEY_CAMERA="camera", KEY_MICROPHONE="microphone",
            KEY_CONNECTIVITY="connectivity", KEY_BRUTEFORCE="bruteforce", KEY_BFU="bfu",
            KEY_INACTIVITY="inactivity", KEY_SECURE_REBOOT="secure_reboot", KEY_TAMPER="tamper";

    private static final int[] BRUTE_FORCE_VALUES={8,10,14,16};
    private static final long[] INACTIVITY_VALUES={86400000L,172800000L,345600000L,604800000L,1209600000L};
    private static final long[] BFU_TIMER_VALUES={3600000L,7200000L,14400000L,21600000L};
    private static final long[] CONNECTIVITY_VALUES={900000L,1800000L};
    private static final int[] TAMPER_VALUES={1,2};

    private ISecureLineManager service;
    private LinearLayout configuration;
    private SecureLineStatusBadge detailsStatusBadge;
    private boolean binding;
    private SecureLineStatusBadge dependentValueButton;
    private String key;

    @Override protected void onCreate(Bundle state) {
        super.onCreate(state);
        setContentView(R.layout.activity_protection_details);
        key=getIntent().getStringExtra(EXTRA_PROTECTION_KEY);
        if (!isValidProtectionKey(key)) { finish(); return; }
        configuration=findViewById(R.id.configuration_container);
        findViewById(R.id.details_back).setOnClickListener(v->finish());
        connectService();
        bindContent();
    }

    private void connectService() {
        try { IBinder b=ServiceManager.waitForService("secureline"); service=ISecureLineManager.Stub.asInterface(b); }
        catch(Throwable t){ service=null; }
    }

    private void bindContent() {
        SecureLineHeroView hero=findViewById(R.id.details_hero);
        TextView what=findViewById(R.id.details_what), important=findViewById(R.id.details_important);
        TextView recommendation=findViewById(R.id.details_recommendation);
        SecureLineTimelineView timeline=findViewById(R.id.details_timeline);
        detailsStatusBadge=findViewById(R.id.details_status_badge);
        hero.setTitle(getString(titleRes()));
        hero.setSubtitle(getString(subtitleRes()));
        hero.setIconResource(iconRes());
        // All detail pages share the same 84dp hero box with an icon filling ~80%.
        hero.setDetailIconSize(116, 7);
        what.setText(descriptionRes());
        timeline.setSteps(
                new CharSequence[] {
                        getText(stepTitleRes(1)),
                        getText(stepTitleRes(2)),
                        getText(stepTitleRes(3))
                },
                new CharSequence[] {
                        getText(stepDescriptionRes(1)),
                        getText(stepDescriptionRes(2)),
                        getText(stepDescriptionRes(3))
                }
        );
        recommendation.setText(recommendationRes());
        important.setText(importantRes());
        if(service==null){ detailsStatusBadge.setText(R.string.unknown); detailsStatusBadge.setBadgeType(SecureLineStatusBadge.TYPE_NEUTRAL); addBody(R.string.service_unavailable); return; }
        try {
            bindStatusBadge(detailsStatusBadge);
        } catch (Exception error) {
            detailsStatusBadge.setText(R.string.unknown);
            detailsStatusBadge.setBadgeType(SecureLineStatusBadge.TYPE_NEUTRAL);
        }
        binding=true;
        try {
            buildConfiguration();
        } catch(Exception e){ configuration.removeAllViews(); addBody(R.string.service_unavailable); }
        binding=false;
    }

    private void buildConfiguration() throws Exception {
        switch(key){
            case KEY_REMOTE: addBody(R.string.remote_wipe_configuration); addPortalLink(); break;
            case KEY_USB: addSwitch(R.string.enable, service.isUsbProtectionEnabled(), checked->service.setUsbProtectionEnabled(checked)); break;
            case KEY_PANIC: addSwitch(R.string.enable, service.isPanicProtectionEnabled(), checked->service.setPanicProtectionEnabled(checked)); break;
            case KEY_CALL: addSwitch(R.string.enable, service.isCallUnlockProtectionEnabled(), checked->service.setCallUnlockProtectionEnabled(checked)); break;
            case KEY_MESSAGE: buildMessageWipe(); break;
            case KEY_CAMERA: addSwitch(R.string.enable, service.isCameraLockdownEnabled(), checked->service.setCameraLockdownEnabled(checked)); break;
            case KEY_MICROPHONE: addSwitch(R.string.enable, service.isMicrophoneLockdownEnabled(), checked->service.setMicrophoneLockdownEnabled(checked)); break;
            case KEY_CONNECTIVITY: {
                addSwitch(R.string.enable, service.isConnectivitySabotageProtectionEnabled(), checked->service.setConnectivitySabotageProtectionEnabled(checked));
                int selected = indexOf(CONNECTIVITY_VALUES, service.getConnectivitySabotageTimeoutMs());
                if (selected >= 0) addValueButton(R.array.connectivity_labels, selected, false, pos->service.setConnectivitySabotageTimeoutMs(CONNECTIVITY_VALUES[pos]));
                else addBody(R.string.unknown_configuration);
                break;
            }
            case KEY_BRUTEFORCE: {
                int selected = indexOf(BRUTE_FORCE_VALUES, service.getBruteForceLimit());
                if (selected >= 0) addValueButton(R.array.bruteforce_labels, selected, true, pos->service.setBruteForceLimit(BRUTE_FORCE_VALUES[pos]));
                else addBody(R.string.unknown_configuration);
                break;
            }
            case KEY_BFU:
                addSwitch(R.string.enable,service.isBfuProtectionEnabled(),checked->service.setBfuProtectionEnabled(checked)); break;
            case KEY_INACTIVITY: {
                int selected = indexOf(INACTIVITY_VALUES, service.getInactivityTimeoutMs());
                if (selected >= 0) addValueButton(R.array.inactivity_labels, selected, true, pos->service.setInactivityTimeoutMs(INACTIVITY_VALUES[pos]));
                else addBody(R.string.unknown_configuration);
                break;
            }
            case KEY_SECURE_REBOOT: {
                int selected = indexOf(BFU_TIMER_VALUES, service.getBfuTimerTimeoutMs());
                if (selected >= 0) addValueButton(R.array.bfu_timer_labels, selected, false, pos -> service.setBfuTimerTimeoutMs(BFU_TIMER_VALUES[pos]));
                else addBody(R.string.unknown_configuration);
                break;
            }
            case KEY_TAMPER: {
                addSwitch(R.string.enable,service.isTamperLockEnabled(),checked->service.setTamperLockEnabled(checked));
                int selected = indexOf(TAMPER_VALUES, service.getTamperSensitivity());
                if (selected >= 0) addValueButton(R.array.tamper_labels, selected, false, pos->service.setTamperSensitivity(TAMPER_VALUES[pos]));
                else addBody(R.string.unknown_configuration);
                break;
            }
        }
    }

    private void buildMessageWipe() throws Exception {
        addSwitch(R.string.enable,service.isMessageWipeProtectionEnabled(),checked->service.setMessageWipeProtectionEnabled(checked));
        EditText input=new EditText(this); input.setHint(R.string.message_wipe_secret_hint); input.setSingleLine(true); input.setInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD); input.setTextColor(getColor(R.color.sl_color_text_primary)); input.setHintTextColor(getColor(R.color.sl_color_text_muted));
        LinearLayout.LayoutParams ip=new LinearLayout.LayoutParams(-1,-2); ip.topMargin=dp(16); configuration.addView(input,ip);
        Button save=new Button(this); save.setText(R.string.message_wipe_save); save.setTextAppearance(R.style.SecureLineUI_Text_Heading); save.setBackgroundResource(R.drawable.sl_button_primary);
        LinearLayout.LayoutParams bp=new LinearLayout.LayoutParams(-1,dp(56)); bp.topMargin=dp(20); configuration.addView(save,bp);
        save.setOnClickListener(v->{ String secret=input.getText().toString().trim(); if(secret.length()<12){toast(R.string.message_wipe_secret_too_short);return;} if(secret.matches(".*\\s+.*")){toast(R.string.message_wipe_secret_no_spaces);return;} confirmSecretCodeChange(()->{service.setMessageWipeSecret(secret);input.setText("");toast(R.string.message_wipe_secret_saved);}); });
    }

    private void addPortalLink() {
        TextView link=new TextView(this); link.setText(R.string.remote_wipe_portal); link.setTextColor(getColor(R.color.sl_color_blue_soft)); link.setTextSize(15); link.setPadding(0,dp(22),0,dp(6));
        link.setOnClickListener(v->startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.remote_wipe_portal_url)))));
        configuration.addView(link,new LinearLayout.LayoutParams(-1,-2));
    }

    private void addBody(int res){ TextView t=new TextView(this); t.setText(res); t.setTextAppearance(R.style.SecureLineUI_Text_Body); configuration.addView(t,new LinearLayout.LayoutParams(-1,-2)); }
    private void addSwitch(int labelRes, boolean checked, CheckedAction action){
        LinearLayout row = new LinearLayout(this);
        row.setOrientation(LinearLayout.HORIZONTAL);
        row.setGravity(android.view.Gravity.CENTER_VERTICAL);

        TextView label = new TextView(this);
        label.setText(labelRes);
        label.setTextAppearance(R.style.SecureLineUI_Text_Heading);
        label.setGravity(android.view.Gravity.CENTER_VERTICAL);
        row.addView(label, new LinearLayout.LayoutParams(0, dp(56), 1f));

        SecureLineStatusBadge button = new SecureLineStatusBadge(this);
        updateToggleBadge(button, checked);
        button.setClickable(true);
        button.setFocusable(true);
        row.addView(button, new LinearLayout.LayoutParams(-2, -2));
        configuration.addView(row, new LinearLayout.LayoutParams(-1, dp(56)));

        button.setOnClickListener(v -> {
            if (binding) return;
            boolean next = !isBadgeEnabled(button);
            confirmDetailToggle(next, () -> {
                action.run(next);
                updateToggleBadge(button, next);
                updateDependentValueButton(next);
                refreshStatusBadge();
            });
        });
    }

    private boolean isBadgeEnabled(SecureLineStatusBadge badge) {
        return getString(R.string.on).contentEquals(badge.getText());
    }

    private void updateToggleBadge(SecureLineStatusBadge badge, boolean enabled) {
        badge.setText(enabled ? R.string.on : R.string.off);
        badge.setBadgeType(enabled ? SecureLineStatusBadge.TYPE_ACTIVE : SecureLineStatusBadge.TYPE_NEUTRAL);
    }

    private void confirmDetailToggle(boolean enabling, RemoteAction action) {
        final String protectionName = getString(titleRes());
        final CharSequence dialogTitle;
        final String message;

        if (enabling && isWipeFeature()) {
            dialogTitle = getString(R.string.security_warning);
            message = getString(R.string.wipe_enable_confirmation_message, protectionName);
        } else if (enabling) {
            dialogTitle = getString(R.string.turn_on_named_protection, protectionName);
            message = getString(R.string.enable_confirmation_message, protectionName);
        } else {
            dialogTitle = getString(R.string.turn_off_named_protection, protectionName);
            message = getString(R.string.disable_confirmation_message, protectionName);
        }

        new AlertDialog.Builder(this, R.style.SecureLineUI_Dialog)
                .setTitle(dialogTitle)
                .setMessage(message)
                .setPositiveButton(enabling ? R.string.turn_on : R.string.turn_off,
                        (dialog, which) -> runRemote(action))
                .setNegativeButton(R.string.cancel, null)
                .show();
    }

    private void updateDependentValueButton(boolean enabled) {
        if (dependentValueButton == null) return;
        dependentValueButton.setEnabled(enabled);
        dependentValueButton.setClickable(enabled);
        dependentValueButton.setFocusable(enabled);
        dependentValueButton.setAlpha(enabled ? 1f : 0.72f);
        dependentValueButton.setBadgeType(enabled
                ? SecureLineStatusBadge.TYPE_ACTIVE
                : SecureLineStatusBadge.TYPE_NEUTRAL);
    }

    private void addValueButton(
            int labelsRes,
            int selected,
            boolean destructive,
            PositionAction action
    ) {
        CharSequence[] labels = getResources().getTextArray(labelsRes);
        SecureLineStatusBadge button = new SecureLineStatusBadge(this);
        button.setText(labels[selected]);
        button.setClickable(true);
        button.setFocusable(true);

        boolean dependsOnToggle = KEY_CONNECTIVITY.equals(key) || KEY_TAMPER.equals(key);
        boolean enabled = true;
        if (dependsOnToggle) {
            try {
                enabled = KEY_CONNECTIVITY.equals(key)
                        ? service.isConnectivitySabotageProtectionEnabled()
                        : service.isTamperLockEnabled();
            } catch (Exception ignored) {
                enabled = false;
            }
            dependentValueButton = button;
        }
        button.setBadgeType(enabled
                ? SecureLineStatusBadge.TYPE_ACTIVE
                : SecureLineStatusBadge.TYPE_NEUTRAL);
        button.setEnabled(enabled);
        button.setClickable(enabled);
        button.setFocusable(enabled);
        button.setAlpha(enabled ? 1f : 0.72f);

        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(-2, -2);
        params.topMargin = dp(12);
        configuration.addView(button, params);

        button.setOnClickListener(v -> {
            if (binding || !button.isEnabled()) return;
            new AlertDialog.Builder(this, R.style.SecureLineUI_Dialog)
                    .setTitle(R.string.current_configuration)
                    .setItems(labels, (dialog, position) ->
                            confirmValueChange(labels[position], destructive, () -> {
                                action.run(position);
                                button.setText(labels[position]);
                                refreshStatusBadge();
                            }))
                    .show();
        });
    }

    private void bindStatusBadge(SecureLineStatusBadge badge) throws Exception {
        if (KEY_REMOTE.equals(key)) { badge.setText(R.string.always_active); badge.setBadgeType(SecureLineStatusBadge.TYPE_ACTIVE); return; }
        if (KEY_BRUTEFORCE.equals(key)) { badge.setText(labelForInt(R.array.bruteforce_labels, BRUTE_FORCE_VALUES, service.getBruteForceLimit())); badge.setBadgeType(SecureLineStatusBadge.TYPE_ACTIVE); return; }
        if (KEY_INACTIVITY.equals(key)) { badge.setText(labelForLong(R.array.inactivity_labels, INACTIVITY_VALUES, service.getInactivityTimeoutMs())); badge.setBadgeType(SecureLineStatusBadge.TYPE_ACTIVE); return; }
        if (KEY_SECURE_REBOOT.equals(key)) { badge.setText(labelForLong(R.array.bfu_timer_labels, BFU_TIMER_VALUES, service.getBfuTimerTimeoutMs())); badge.setBadgeType(SecureLineStatusBadge.TYPE_ACTIVE); return; }
        boolean enabled;
        switch (key) {
            case KEY_USB: enabled=service.isUsbProtectionEnabled(); break;
            case KEY_PANIC: enabled=service.isPanicProtectionEnabled(); break;
            case KEY_CALL: enabled=service.isCallUnlockProtectionEnabled(); break;
            case KEY_MESSAGE: enabled=service.isMessageWipeProtectionEnabled(); break;
            case KEY_CAMERA: enabled=service.isCameraLockdownEnabled(); break;
            case KEY_MICROPHONE: enabled=service.isMicrophoneLockdownEnabled(); break;
            case KEY_CONNECTIVITY: enabled=service.isConnectivitySabotageProtectionEnabled(); break;
            case KEY_BFU: enabled=service.isBfuProtectionEnabled(); break;
            case KEY_TAMPER: enabled=service.isTamperLockEnabled(); break;
            default: enabled=false;
        }
        badge.setText(enabled ? R.string.on : R.string.off);
        badge.setBadgeType(enabled ? SecureLineStatusBadge.TYPE_ACTIVE : SecureLineStatusBadge.TYPE_NEUTRAL);
    }

    private CharSequence labelForInt(int res, int[] values, int current) { CharSequence[] labels=getResources().getTextArray(res); for(int i=0;i<values.length&&i<labels.length;i++) if(values[i]==current) return labels[i]; return getString(R.string.unknown); }
    private CharSequence labelForLong(int res, long[] values, long current) { CharSequence[] labels=getResources().getTextArray(res); for(int i=0;i<values.length&&i<labels.length;i++) if(values[i]==current) return labels[i]; return getString(R.string.unknown); }

    private void confirmValueChange(
            CharSequence newValue,
            boolean destructive,
            RemoteAction action
    ) {
        final String protectionName = getString(titleRes());
        final CharSequence title = destructive
                ? getString(R.string.security_warning)
                : getString(R.string.change_named_protection, protectionName);
        final String message = destructive
                ? getString(R.string.wipe_value_change_confirmation_message,
                        protectionName, newValue)
                : getString(R.string.value_change_confirmation_message,
                        protectionName, newValue);

        new AlertDialog.Builder(this, R.style.SecureLineUI_Dialog)
                .setTitle(title)
                .setMessage(message)
                .setPositiveButton(R.string.change, (dialog, which) -> runRemote(action))
                .setNegativeButton(R.string.cancel, null)
                .show();
    }

    private void confirmSecretCodeChange(RemoteAction action) {
        final String protectionName = getString(titleRes());
        new AlertDialog.Builder(this, R.style.SecureLineUI_Dialog)
                .setTitle(R.string.security_warning)
                .setMessage(getString(R.string.secret_code_change_confirmation_message,
                        protectionName))
                .setPositiveButton(R.string.save, (dialog, which) -> runRemote(action))
                .setNegativeButton(R.string.cancel, null)
                .show();
    }
    private void runRemote(RemoteAction action){
        try { action.run(); refreshStatusBadge(); }
        catch(Exception e){ toast(R.string.service_unavailable); }
    }
    private void refreshStatusBadge() {
        if (detailsStatusBadge == null || service == null) return;
        try { bindStatusBadge(detailsStatusBadge); }
        catch (Exception error) {
            detailsStatusBadge.setText(R.string.unknown);
            detailsStatusBadge.setBadgeType(SecureLineStatusBadge.TYPE_NEUTRAL);
        }
    }
    private void toast(int r){Toast.makeText(this,r,Toast.LENGTH_SHORT).show();}
    private int dp(int n){return Math.round(n*getResources().getDisplayMetrics().density);}
    private int indexOf(long[] a,long v){for(int i=0;i<a.length;i++)if(a[i]==v)return i;return -1;}
    private int indexOf(int[] a,int v){for(int i=0;i<a.length;i++)if(a[i]==v)return i;return -1;}

    private boolean isValidProtectionKey(String value) {
        return KEY_REMOTE.equals(value)
                || KEY_USB.equals(value)
                || KEY_PANIC.equals(value)
                || KEY_CALL.equals(value)
                || KEY_MESSAGE.equals(value)
                || KEY_CAMERA.equals(value)
                || KEY_MICROPHONE.equals(value)
                || KEY_CONNECTIVITY.equals(value)
                || KEY_BRUTEFORCE.equals(value)
                || KEY_BFU.equals(value)
                || KEY_INACTIVITY.equals(value)
                || KEY_SECURE_REBOOT.equals(value)
                || KEY_TAMPER.equals(value);
    }


    private int stepTitleRes(int step) {
        return getResources().getIdentifier(key + "_step_" + step + "_title", "string", getPackageName());
    }

    private int stepDescriptionRes(int step) {
        return getResources().getIdentifier(key + "_step_" + step + "_description", "string", getPackageName());
    }

    private int recommendationRes() {
        return getResources().getIdentifier(key + "_recommendation", "string", getPackageName());
    }

    private int importantRes() {
        if (isWipeFeature()) return R.string.wipe_protection_important;
        if (KEY_CAMERA.equals(key)) return R.string.camera_important;
        if (KEY_MICROPHONE.equals(key)) return R.string.microphone_important;
        if (KEY_CALL.equals(key)) return R.string.call_important;
        if (KEY_TAMPER.equals(key)) return R.string.tamper_important;
        if (KEY_CONNECTIVITY.equals(key)) return R.string.connectivity_important;
        if (KEY_BFU.equals(key)) return R.string.bfu_enable_important;
        if (KEY_SECURE_REBOOT.equals(key)) return R.string.bfu_configuration_important;
        return R.string.non_wipe_information;
    }

    private int iconRes(){switch(key){case KEY_REMOTE:return R.drawable.ic_remote_wipe;case KEY_USB:return R.drawable.ic_usb;case KEY_PANIC:return R.drawable.ic_panic;case KEY_CALL:return R.drawable.ic_call_unlock;case KEY_MESSAGE:return R.drawable.ic_message_wipe;case KEY_CAMERA:return R.drawable.ic_camera;case KEY_MICROPHONE:return R.drawable.ic_microphone;case KEY_CONNECTIVITY:return R.drawable.ic_connectivity;case KEY_BRUTEFORCE:return R.drawable.ic_bruteforce;case KEY_BFU:return R.drawable.ic_reboot;case KEY_INACTIVITY:return R.drawable.ic_inactivity;case KEY_SECURE_REBOOT:return R.drawable.ic_secure_reboot;default:return R.drawable.ic_tamper;}}
    private boolean isWipeFeature(){return key.equals(KEY_REMOTE)||key.equals(KEY_USB)||key.equals(KEY_PANIC)||key.equals(KEY_MESSAGE)||key.equals(KEY_BRUTEFORCE)||key.equals(KEY_INACTIVITY);}
    private int titleRes(){switch(key){case KEY_REMOTE:return R.string.remote_wipe;case KEY_USB:return R.string.usb_protection;case KEY_PANIC:return R.string.panic_protection;case KEY_CALL:return R.string.call_unlock_protection;case KEY_MESSAGE:return R.string.message_wipe_protection;case KEY_CAMERA:return R.string.camera_lockdown_protection;case KEY_MICROPHONE:return R.string.microphone_lockdown_protection;case KEY_CONNECTIVITY:return R.string.connectivity_protection;case KEY_BRUTEFORCE:return R.string.bruteforce_protection;case KEY_BFU:return R.string.bruteforce_reboot_protection;case KEY_INACTIVITY:return R.string.inactivity_protection;case KEY_SECURE_REBOOT:return R.string.secure_reboot_protection;default:return R.string.device_tamper_protection;}}
    private int subtitleRes(){switch(key){case KEY_REMOTE:return R.string.remote_wipe_subtitle;case KEY_USB:return R.string.usb_protection_subtitle;case KEY_PANIC:return R.string.panic_protection_subtitle;case KEY_CALL:return R.string.call_unlock_protection_subtitle;case KEY_MESSAGE:return R.string.message_wipe_protection_subtitle;case KEY_CAMERA:return R.string.camera_lockdown_subtitle;case KEY_MICROPHONE:return R.string.microphone_lockdown_subtitle;case KEY_CONNECTIVITY:return R.string.connectivity_protection_subtitle;case KEY_BRUTEFORCE:return R.string.bruteforce_protection_subtitle;case KEY_BFU:return R.string.bruteforce_reboot_protection_subtitle;case KEY_INACTIVITY:return R.string.inactivity_protection_subtitle;case KEY_SECURE_REBOOT:return R.string.secure_reboot_protection_subtitle;default:return R.string.device_tamper_protection_subtitle;}}
    private int descriptionRes(){switch(key){case KEY_REMOTE:return R.string.remote_wipe_desc;case KEY_USB:return R.string.usb_protection_desc;case KEY_PANIC:return R.string.panic_protection_desc;case KEY_CALL:return R.string.call_unlock_protection_desc;case KEY_MESSAGE:return R.string.message_wipe_protection_desc;case KEY_CAMERA:return R.string.camera_lockdown_desc;case KEY_MICROPHONE:return R.string.microphone_lockdown_desc;case KEY_CONNECTIVITY:return R.string.connectivity_protection_desc;case KEY_BRUTEFORCE:return R.string.bruteforce_protection_desc;case KEY_BFU:return R.string.bruteforce_reboot_protection_desc;case KEY_INACTIVITY:return R.string.inactivity_protection_desc;case KEY_SECURE_REBOOT:return R.string.secure_reboot_protection_desc;default:return R.string.device_tamper_protection_desc;}}
    @Override
    public void finish() {
        super.finish();
        overridePendingTransition(0, 0);
    }

    private interface RemoteAction{void run()throws Exception;} private interface CheckedAction{void run(boolean c)throws Exception;} private interface PositionAction{void run(int p)throws Exception;}
}
