/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.net.ipmemorystore.Blob;
import android.net.ipmemorystore.NetworkAttributes;
import android.net.ipmemorystore.OnBlobRetrievedListener;
import android.net.ipmemorystore.OnDeleteStatusListener;
import android.net.ipmemorystore.OnL2KeyResponseListener;
import android.net.ipmemorystore.OnNetworkAttributesRetrievedListener;
import android.net.ipmemorystore.OnSameL3NetworkResponseListener;
import android.net.ipmemorystore.OnStatusListener;
import android.net.ipmemorystore.Status;
import android.os.RemoteException;
import android.util.Log;

import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;

/**
 * service used to communicate with the ip memory store service in network stack,
 * which is running in a separate module.
 * @hide
 */
public abstract class IpMemoryStoreClient {
    private static final String TAG = IpMemoryStoreClient.class.getSimpleName();
    private final Context mContext;

    public IpMemoryStoreClient(@NonNull final Context context) {
        if (context == null) throw new IllegalArgumentException("missing context");
        mContext = context;
    }

    protected abstract void runWhenServiceReady(Consumer<IIpMemoryStore> cb)
            throws ExecutionException;

    @FunctionalInterface
    private interface ThrowingRunnable {
        void run() throws RemoteException;
    }

    private void ignoringRemoteException(ThrowingRunnable r) {
        ignoringRemoteException("Failed to execute remote procedure call", r);
    }

    private void ignoringRemoteException(String message, ThrowingRunnable r) {
        try {
            r.run();
        } catch (RemoteException e) {
            Log.e(TAG, message, e);
        }
    }

    /**
     * Store network attributes for a given L2 key.
     * If L2Key is null, choose automatically from the attributes ; passing null is equivalent to
     * calling findL2Key with the attributes and storing in the returned value.
     *
     * @param l2Key The L2 key for the L2 network. Clients that don't know or care about the L2
     *              key and only care about grouping can pass a unique ID here like the ones
     *              generated by {@code java.util.UUID.randomUUID()}, but keep in mind the low
     *              relevance of such a network will lead to it being evicted soon if it's not
     *              refreshed. Use findL2Key to try and find a similar L2Key to these attributes.
     * @param attributes The attributes for this network.
     * @param listener A listener that will be invoked to inform of the completion of this call,
     *                 or null if the client is not interested in learning about success/failure.
     * Through the listener, returns the L2 key. This is useful if the L2 key was not specified.
     * If the call failed, the L2 key will be null.
     */
    public void storeNetworkAttributes(@NonNull final String l2Key,
            @NonNull final NetworkAttributes attributes,
            @Nullable final OnStatusListener listener) {
        try {
            runWhenServiceReady(service -> ignoringRemoteException(
                    () -> service.storeNetworkAttributes(l2Key, attributes.toParcelable(),
                            OnStatusListener.toAIDL(listener))));
        } catch (ExecutionException m) {
            if (null == listener) return;
            ignoringRemoteException("Error storing network attributes",
                    () -> listener.onComplete(new Status(Status.ERROR_UNKNOWN)));
        }
    }

    /**
     * Store a binary blob associated with an L2 key and a name.
     *
     * @param l2Key The L2 key for this network.
     * @param clientId The ID of the client.
     * @param name The name of this data.
     * @param data The data to store.
     * @param listener A listener to inform of the completion of this call, or null if the client
     *        is not interested in learning about success/failure.
     * Through the listener, returns a status to indicate success or failure.
     */
    public void storeBlob(@NonNull final String l2Key, @NonNull final String clientId,
            @NonNull final String name, @NonNull final Blob data,
            @Nullable final OnStatusListener listener) {
        try {
            runWhenServiceReady(service -> ignoringRemoteException(
                    () -> service.storeBlob(l2Key, clientId, name, data,
                            OnStatusListener.toAIDL(listener))));
        } catch (ExecutionException m) {
            if (null == listener) return;
            ignoringRemoteException("Error storing blob",
                    () -> listener.onComplete(new Status(Status.ERROR_UNKNOWN)));
        }
    }

    /**
     * Returns the best L2 key associated with the attributes.
     *
     * This will find a record that would be in the same group as the passed attributes. This is
     * useful to choose the key for storing a sample or private data when the L2 key is not known.
     * If multiple records are group-close to these attributes, the closest match is returned.
     * If multiple records have the same closeness, the one with the smaller (unicode codepoint
     * order) L2 key is returned.
     * If no record matches these attributes, null is returned.
     *
     * @param attributes The attributes of the network to find.
     * @param listener The listener that will be invoked to return the answer.
     * Through the listener, returns the L2 key if one matched, or null.
     */
    public void findL2Key(@NonNull final NetworkAttributes attributes,
            @NonNull final OnL2KeyResponseListener listener) {
        try {
            runWhenServiceReady(service -> ignoringRemoteException(
                    () -> service.findL2Key(attributes.toParcelable(),
                            OnL2KeyResponseListener.toAIDL(listener))));
        } catch (ExecutionException m) {
            ignoringRemoteException("Error finding L2 Key",
                    () -> listener.onL2KeyResponse(new Status(Status.ERROR_UNKNOWN),
                            null /* l2Key */));
        }
    }

    /**
     * Returns whether, to the best of the store's ability to tell, the two specified L2 keys point
     * to the same L3 network. Group-closeness is used to determine this.
     *
     * @param l2Key1 The key for the first network.
     * @param l2Key2 The key for the second network.
     * @param listener The listener that will be invoked to return the answer.
     * Through the listener, a SameL3NetworkResponse containing the answer and confidence.
     */
    public void isSameNetwork(@NonNull final String l2Key1, @NonNull final String l2Key2,
            @NonNull final OnSameL3NetworkResponseListener listener) {
        try {
            runWhenServiceReady(service -> ignoringRemoteException(
                    () -> service.isSameNetwork(l2Key1, l2Key2,
                            OnSameL3NetworkResponseListener.toAIDL(listener))));
        } catch (ExecutionException m) {
            ignoringRemoteException("Error checking for network sameness",
                    () -> listener.onSameL3NetworkResponse(new Status(Status.ERROR_UNKNOWN),
                            null /* response */));
        }
    }

    /**
     * Retrieve the network attributes for a key.
     * If no record is present for this key, this will return null attributes.
     *
     * @param l2Key The key of the network to query.
     * @param listener The listener that will be invoked to return the answer.
     * Through the listener, returns the network attributes and the L2 key associated with
     *         the query.
     */
    public void retrieveNetworkAttributes(@NonNull final String l2Key,
            @NonNull final OnNetworkAttributesRetrievedListener listener) {
        try {
            runWhenServiceReady(service -> ignoringRemoteException(
                    () -> service.retrieveNetworkAttributes(l2Key,
                            OnNetworkAttributesRetrievedListener.toAIDL(listener))));
        } catch (ExecutionException m) {
            ignoringRemoteException("Error retrieving network attributes",
                    () -> listener.onNetworkAttributesRetrieved(new Status(Status.ERROR_UNKNOWN),
                            null /* l2Key */, null /* attributes */));
        }
    }

    /**
     * Retrieve previously stored private data.
     * If no data was stored for this L2 key and name this will return null.
     *
     * @param l2Key The L2 key.
     * @param clientId The id of the client that stored this data.
     * @param name The name of the data.
     * @param listener The listener that will be invoked to return the answer.
     * Through the listener, returns the private data (or null), with the L2 key
     *         and the name of the data associated with the query.
     */
    public void retrieveBlob(@NonNull final String l2Key, @NonNull final String clientId,
            @NonNull final String name, @NonNull final OnBlobRetrievedListener listener) {
        try {
            runWhenServiceReady(service -> ignoringRemoteException(
                    () -> service.retrieveBlob(l2Key, clientId, name,
                            OnBlobRetrievedListener.toAIDL(listener))));
        } catch (ExecutionException m) {
            ignoringRemoteException("Error retrieving blob",
                    () -> listener.onBlobRetrieved(new Status(Status.ERROR_UNKNOWN),
                            null /* l2Key */, null /* name */, null /* blob */));
        }
    }

    /**
     * Delete a single entry.
     *
     * @param l2Key The L2 key of the entry to delete.
     * @param needWipe Whether the data must be wiped from disk immediately. This makes the
     *                 operation vastly more expensive as the database files will have to be copied
     *                 and created again from the old files (see sqlite3 VACUUM operation for
     *                 details) and makes no functional difference; only pass true if security or
     *                 privacy demands this data must be removed from disk immediately.
     *                 Note that this can fail for storage reasons. The passed listener will then
     *                 receive an appropriate error status with the number of deleted rows.
     * @param listener A listener that will be invoked to inform of the completion of this call,
     *                 or null if the client is not interested in learning about success/failure.
     * returns (through the listener) A status to indicate success and the number of deleted records
     */
    public void delete(@NonNull final String l2Key, final boolean needWipe,
            @Nullable final OnDeleteStatusListener listener) {
        try {
            runWhenServiceReady(service -> ignoringRemoteException(() ->
                    service.delete(l2Key, needWipe, OnDeleteStatusListener.toAIDL(listener))));
        } catch (ExecutionException m) {
            if (null == listener) return;
            ignoringRemoteException("Error deleting from the memory store",
                    () -> listener.onComplete(new Status(Status.ERROR_UNKNOWN),
                            0 /* deletedRecords */));
        }
    }

    /**
     * Delete all entries in a cluster.
     *
     * This method will delete all entries in the memory store that have the cluster attribute
     * passed as an argument.
     *
     * @param cluster The cluster to delete.
     * @param needWipe Whether the data must be wiped from disk immediately. This makes the
     *                 operation vastly more expensive as the database files will have to be copied
     *                 and created again from the old files (see sqlite3 VACUUM operation for
     *                 details) and makes no functional difference; only pass true if security or
     *                 privacy demands this data must be removed from disk immediately.
     *                 Note that this can fail for storage reasons. The passed listener will then
     *                 receive an appropriate error status with the number of deleted rows.
     * @param listener A listener that will be invoked to inform of the completion of this call,
     *                 or null if the client is not interested in learning about success/failure.
     * returns (through the listener) A status to indicate success and the number of deleted records
     */
    public void deleteCluster(@NonNull final String cluster, final boolean needWipe,
            @Nullable final OnDeleteStatusListener listener) {
        try {
            runWhenServiceReady(service -> ignoringRemoteException(
                    () -> service.deleteCluster(cluster, needWipe,
                            OnDeleteStatusListener.toAIDL(listener))));
        } catch (ExecutionException m) {
            if (null == listener) return;
            ignoringRemoteException("Error deleting from the memory store",
                    () -> listener.onComplete(new Status(Status.ERROR_UNKNOWN),
                            0 /* deletedRecords */));
        }
    }

    /**
     * Wipe the data in the database upon network factory reset.
     */
    public void factoryReset() {
        try {
            runWhenServiceReady(service -> ignoringRemoteException(
                    () -> service.factoryReset()));
        } catch (ExecutionException m) {
            Log.e(TAG, "Error executing factory reset", m);
        }
    }
}
