/*
 * Copyright (C) 2018 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 com.android.server.autofill;

import static android.service.autofill.AutofillFieldClassificationService.SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS;
import static android.service.autofill.AutofillFieldClassificationService.SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM;

import static com.android.server.autofill.Helper.sDebug;
import static com.android.server.autofill.Helper.sVerbose;

import android.Manifest;
import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.UserHandle;
import android.service.autofill.AutofillFieldClassificationService;
import android.service.autofill.IAutofillFieldClassificationService;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
import android.view.autofill.AutofillValue;

import com.android.internal.annotations.GuardedBy;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Strategy used to bridge the field classification algorithms provided by a service in an external
 * package.
 */
//TODO(b/70291841): add unit tests ?
final class FieldClassificationStrategy {

    private static final String TAG = "FieldClassificationStrategy";

    private final Context mContext;
    private final Object mLock = new Object();
    private final int mUserId;

    @GuardedBy("mLock")
    private ServiceConnection mServiceConnection;

    @GuardedBy("mLock")
    private IAutofillFieldClassificationService mRemoteService;

    @GuardedBy("mLock")
    private ArrayList<Command> mQueuedCommands;

    public FieldClassificationStrategy(Context context, int userId) {
        mContext = context;
        mUserId = userId;
    }

    @Nullable
    ServiceInfo getServiceInfo() {
        final String packageName =
                mContext.getPackageManager().getServicesSystemSharedLibraryPackageName();
        if (packageName == null) {
            Slog.w(TAG, "no external services package!");
            return null;
        }

        final Intent intent = new Intent(AutofillFieldClassificationService.SERVICE_INTERFACE);
        intent.setPackage(packageName);
        final ResolveInfo resolveInfo = mContext.getPackageManager().resolveService(intent,
                PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
        if (resolveInfo == null || resolveInfo.serviceInfo == null) {
            Slog.w(TAG, "No valid components found.");
            return null;
        }
        return resolveInfo.serviceInfo;
    }

    @Nullable
    private ComponentName getServiceComponentName() {
        final ServiceInfo serviceInfo = getServiceInfo();
        if (serviceInfo == null) return null;

        final ComponentName name = new ComponentName(serviceInfo.packageName, serviceInfo.name);
        if (!Manifest.permission.BIND_AUTOFILL_FIELD_CLASSIFICATION_SERVICE
                .equals(serviceInfo.permission)) {
            Slog.w(TAG, name.flattenToShortString() + " does not require permission "
                    + Manifest.permission.BIND_AUTOFILL_FIELD_CLASSIFICATION_SERVICE);
            return null;
        }

        if (sVerbose) Slog.v(TAG, "getServiceComponentName(): " + name);
        return name;
    }

    void reset() {
        synchronized (mLock) {
            if (mServiceConnection != null) {
                if (sDebug) Slog.d(TAG, "reset(): unbinding service.");
                mContext.unbindService(mServiceConnection);
                mServiceConnection = null;
            } else {
                if (sDebug) Slog.d(TAG, "reset(): service is not bound. Do nothing.");
            }
        }
    }

    /**
     * Run a command, starting the service connection if necessary.
     */
    private void connectAndRun(@NonNull Command command) {
        synchronized (mLock) {
            if (mRemoteService != null) {
                try {
                    if (sVerbose) Slog.v(TAG, "running command right away");
                    command.run(mRemoteService);
                } catch (RemoteException e) {
                    Slog.w(TAG, "exception calling service: " + e);
                }
                return;
            } else {
                if (sDebug) Slog.d(TAG, "service is null; queuing command");
                if (mQueuedCommands == null) {
                    mQueuedCommands = new ArrayList<>(1);
                }
                mQueuedCommands.add(command);
                // If we're already connected, don't create a new connection, just leave - the
                // command will be run when the service connects
                if (mServiceConnection != null) return;
            }

            if (sVerbose) Slog.v(TAG, "creating connection");

            // Create the connection
            mServiceConnection = new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    if (sVerbose) Slog.v(TAG, "onServiceConnected(): " + name);
                    synchronized (mLock) {
                        mRemoteService = IAutofillFieldClassificationService.Stub
                                .asInterface(service);
                        if (mQueuedCommands != null) {
                            final int size = mQueuedCommands.size();
                            if (sDebug) Slog.d(TAG, "running " + size + " queued commands");
                            for (int i = 0; i < size; i++) {
                                final Command queuedCommand = mQueuedCommands.get(i);
                                try {
                                    if (sVerbose) Slog.v(TAG, "running queued command #" + i);
                                    queuedCommand.run(mRemoteService);
                                } catch (RemoteException e) {
                                    Slog.w(TAG, "exception calling " + name + ": " + e);
                                }
                            }
                            mQueuedCommands = null;
                        } else if (sDebug) Slog.d(TAG, "no queued commands");
                    }
                }

                @Override
                @MainThread
                public void onServiceDisconnected(ComponentName name) {
                    if (sVerbose) Slog.v(TAG, "onServiceDisconnected(): " + name);
                    synchronized (mLock) {
                        mRemoteService = null;
                    }
                }

                @Override
                public void onBindingDied(ComponentName name) {
                    if (sVerbose) Slog.v(TAG, "onBindingDied(): " + name);
                    synchronized (mLock) {
                        mRemoteService = null;
                    }
                }

                @Override
                public void onNullBinding(ComponentName name) {
                    if (sVerbose) Slog.v(TAG, "onNullBinding(): " + name);
                    synchronized (mLock) {
                        mRemoteService = null;
                    }
                }
            };

            final ComponentName component = getServiceComponentName();
            if (sVerbose) Slog.v(TAG, "binding to: " + component);
            if (component != null) {
                final Intent intent = new Intent();
                intent.setComponent(component);
                final long token = Binder.clearCallingIdentity();
                try {
                    mContext.bindServiceAsUser(intent, mServiceConnection, Context.BIND_AUTO_CREATE,
                            UserHandle.of(mUserId));
                    if (sVerbose) Slog.v(TAG, "bound");
                } finally {
                    Binder.restoreCallingIdentity(token);
                }
            }
        }
    }

    /**
     * Gets the name of all available algorithms.
     */
    @Nullable
    String[] getAvailableAlgorithms() {
        return getMetadataValue(SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS,
                (res, id) -> res.getStringArray(id));
    }

    /**
     * Gets the default algorithm that's used when an algorithm is not specified or is invalid.
     */
    @Nullable
    String getDefaultAlgorithm() {
        return getMetadataValue(SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM, (res, id) -> res.getString(id));
    }

    @Nullable
    private <T> T getMetadataValue(String field, MetadataParser<T> parser) {
        final ServiceInfo serviceInfo = getServiceInfo();
        if (serviceInfo == null) return null;

        final PackageManager pm = mContext.getPackageManager();

        final Resources res;
        try {
            res = pm.getResourcesForApplication(serviceInfo.applicationInfo);
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG, "Error getting application resources for " + serviceInfo, e);
            return null;
        }

        final int resourceId = serviceInfo.metaData.getInt(field);
        return parser.get(res, resourceId);
    }

    void calculateScores(RemoteCallback callback, @NonNull List<AutofillValue> actualValues,
            @NonNull String[] userDataValues, @NonNull String[] categoryIds,
            @Nullable String defaultAlgorithm, @Nullable Bundle defaultArgs,
            @Nullable ArrayMap<String, String> algorithms,
            @Nullable ArrayMap<String, Bundle> args) {
        connectAndRun((service) -> service.calculateScores(callback, actualValues,
                userDataValues, categoryIds, defaultAlgorithm, defaultArgs, algorithms, args));
    }

    void dump(String prefix, PrintWriter pw) {
        final ComponentName impl = getServiceComponentName();
        pw.print(prefix); pw.print("User ID: "); pw.println(mUserId);
        pw.print(prefix); pw.print("Queued commands: ");
        if (mQueuedCommands == null) {
            pw.println("N/A");
        } else {
            pw.println(mQueuedCommands.size());
        }
        pw.print(prefix); pw.print("Implementation: ");
        if (impl == null) {
            pw.println("N/A");
            return;
        }
        pw.println(impl.flattenToShortString());

        try {
            pw.print(prefix); pw.print("Available algorithms: ");
            pw.println(Arrays.toString(getAvailableAlgorithms()));
            pw.print(prefix); pw.print("Default algorithm: "); pw.println(getDefaultAlgorithm());
        } catch (Exception e) {
            pw.print("ERROR CALLING SERVICE: " ); pw.println(e);
        }
    }

    private static interface Command {
        void run(IAutofillFieldClassificationService service) throws RemoteException;
    }

    private static interface MetadataParser<T> {
        T get(Resources res, int resId);
    }
}
