/*
 * 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.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) {
            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) {
            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));
        }
    }

    /**
     * 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));
        }
    }

    /**
     * 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, null));
        }
    }

    /**
     * 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, null, null));
        }
    }

    /**
     * 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);
        }
    }
}
