package com.topjohnwu.magisk.utils;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Base64;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.safetynet.SafetyNet;

import org.json.JSONException;
import org.json.JSONObject;

import java.security.SecureRandom;

public abstract class SafetyNetHelper
        implements GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks {

    private GoogleApiClient mGoogleApiClient;

    public SafetyNetHelper(Context context) {
        mGoogleApiClient = new GoogleApiClient.Builder(context)
                .addApi(SafetyNet.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult result) {
        Logger.dev("SN: Google API fail");
        handleResults(-2);
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        Logger.dev("SN: Google API Connected");
        safetyNetCheck();
    }

    @Override
    public void onConnectionSuspended(int i) {
        Logger.dev("SN: Google API Suspended");
        handleResults(-3);
    }

    public void requestTest() {
        // Connect Google Service
        mGoogleApiClient.connect();
    }

    private void safetyNetCheck() {
        // Create nonce
        byte[] nonce = new byte[24];
        new SecureRandom().nextBytes(nonce);

        Logger.dev("SN: Check with nonce: " + Base64.encodeToString(nonce, Base64.DEFAULT));

        // Call SafetyNet
        SafetyNet.SafetyNetApi.attest(mGoogleApiClient, nonce)
                .setResultCallback(result -> {
                    Status status = result.getStatus();
                    if (status.isSuccess()) {
                        String json = new String(Base64.decode(result.getJwsResult().split("\\.")[1], Base64.DEFAULT));
                        Logger.dev("SN: Response: " + json);
                        try {
                            JSONObject decoded = new JSONObject(json);
                            handleResults(decoded.getBoolean("ctsProfileMatch") ? 1 : 0);
                        } catch (JSONException ignored) {}
                    } else {
                        Logger.dev("SN: No response");
                        handleResults(-1);
                    }
                    // Disconnect
                    mGoogleApiClient.disconnect();
                });
    }

    public abstract void handleResults(int i);
}
