package com.secureline.server;

import android.util.Slog;

import org.json.JSONObject;

import java.nio.charset.StandardCharsets;

public class SecureLineCommandProcessor {

private static final String TAG = "SecureLineCommandProcessor";

private final SecureLineManagerService mService;

private final SecureLineCommandStore mCommandStore;

public SecureLineCommandProcessor(SecureLineManagerService service) {
    mService = service;
    mCommandStore = new SecureLineCommandStore(service.getContext());
}

public void process(JSONObject cmd) throws Exception {

    byte[] cmdBytes = mCommandStore.load();

    if (cmdBytes == null) {
        Slog.e(TAG, "Command store missing, ignoring command");
        return;
    }

    JSONObject identity =
            new JSONObject(new String(cmdBytes, StandardCharsets.UTF_8));

    // =====================================================
    // Command version check
    // =====================================================

    int version = cmd.optInt("v", 1);

    if (version != 1) {
        Slog.w(TAG, "Unsupported command version: " + version);
        return;
    }

    // =====================================================
    // Device Binding Check
    // =====================================================

    String localDeviceId =
            identity.getString("device_id");

    String targetDeviceId =
            cmd.getString("device_id");

    if (!localDeviceId.equals(targetDeviceId)) {

        Slog.w(TAG,
                "Command device mismatch target=" +
                targetDeviceId + " local=" + localDeviceId);

        return;
    }

    // =====================================================
    // Anti Replay Protection
    // =====================================================

    long lastCounter =
            identity.optLong("last_command_counter", 0);

    long counter =
            cmd.getLong("command_counter");

    if (counter <= lastCounter) {

        Slog.w(TAG,
                "Ignoring replayed command counter=" + counter +
                        " last=" + lastCounter);

        return;
    }

    // =====================================================
    // Command execution
    // =====================================================

    boolean executed = false;

    String type = cmd.getString("type");

    if ("OWNER_WIPE".equals(type)) {

	executed = true;

        Slog.w(TAG, "Executing OWNER_WIPE command");

        mService.triggerImmediateWipe("remote_wipe");

    }

    // =====================================================
    // Developer security policy
    // =====================================================

    if ("SET_DEVELOPER_POLICY".equals(type)) {

    executed = true;

    boolean debuggingAllowed =
            cmd.optBoolean(
                    "debugging_allowed",
                    true
            );

    boolean oemAllowed =
            cmd.optBoolean(
                    "bootloader_unlock_allowed",
                    true
            );

    Slog.i(
            TAG,
            "Applying developer policy debugging="
                    + debuggingAllowed
                    + " oem="
                    + oemAllowed
    );

    mService.setDebuggingAllowed(
            debuggingAllowed
    );

    mService.setBootloaderUnlockAllowed(
            oemAllowed
    );
    }

    if (executed) {

    identity.put("last_command_counter", counter);

    mCommandStore.store(
            identity.toString().getBytes(StandardCharsets.UTF_8)
    );


    // =====================================================
    // Unknown command
    // =====================================================
    } else {

        Slog.w(TAG, "Unknown command type: " + type);
    }
}
}
