/*
 * 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 android.content;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.app.ActivityThread;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArraySet;
import android.util.Log;
import android.view.contentcapture.ContentCaptureManager;
import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;

import com.android.internal.annotations.VisibleForTesting;

import java.io.PrintWriter;

/**
 * Content capture options for a given package.
 *
 * <p>This object is created by the Content Capture System Service and passed back to the app when
 * the application is created.
 *
 * @hide
 */
@TestApi
public final class ContentCaptureOptions implements Parcelable {

    private static final String TAG = ContentCaptureOptions.class.getSimpleName();

    /**
     * Logging level for {@code logcat} statements.
     */
    public final int loggingLevel;

    /**
     * Maximum number of events that are buffered before sent to the app.
     */
    public final int maxBufferSize;

    /**
     * Frequency the buffer is flushed if idle.
     */
    public final int idleFlushingFrequencyMs;

    /**
     * Frequency the buffer is flushed if last event is a text change.
     */
    public final int textChangeFlushingFrequencyMs;

    /**
     * Size of events that are logging on {@code dump}.
     */
    public final int logHistorySize;

    /**
     * List of activities explicitly whitelisted for content capture (or {@code null} if whitelisted
     * for all acitivites in the package).
     */
    @Nullable
    public final ArraySet<ComponentName> whitelistedComponents;

    /**
     * Used to enable just a small set of APIs so it can used by activities belonging to the
     * content capture service APK.
     */
    public final boolean lite;

    /**
     * Constructor for "lite" objects that are just used to enable a {@link ContentCaptureManager}
     * for contexts belonging to the content capture service app.
     */
    public ContentCaptureOptions(int loggingLevel) {
        this(/* lite= */ true, loggingLevel, /* maxBufferSize= */ 0,
                /* idleFlushingFrequencyMs= */ 0, /* textChangeFlushingFrequencyMs= */ 0,
                /* logHistorySize= */ 0, /* whitelistedComponents= */ null);
    }

    /**
     * Default constructor.
     */
    public ContentCaptureOptions(int loggingLevel, int maxBufferSize, int idleFlushingFrequencyMs,
            int textChangeFlushingFrequencyMs, int logHistorySize,
            @Nullable ArraySet<ComponentName> whitelistedComponents) {
        this(/* lite= */ false, loggingLevel, maxBufferSize, idleFlushingFrequencyMs,
                textChangeFlushingFrequencyMs, logHistorySize, whitelistedComponents);
    }

    /** @hide */
    @VisibleForTesting
    public ContentCaptureOptions(@Nullable ArraySet<ComponentName> whitelistedComponents) {
        this(ContentCaptureManager.LOGGING_LEVEL_VERBOSE,
                ContentCaptureManager.DEFAULT_MAX_BUFFER_SIZE,
                ContentCaptureManager.DEFAULT_IDLE_FLUSHING_FREQUENCY_MS,
                ContentCaptureManager.DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS,
                ContentCaptureManager.DEFAULT_LOG_HISTORY_SIZE, whitelistedComponents);
    }

    private ContentCaptureOptions(boolean lite, int loggingLevel, int maxBufferSize,
            int idleFlushingFrequencyMs, int textChangeFlushingFrequencyMs, int logHistorySize,
            @Nullable ArraySet<ComponentName> whitelistedComponents) {
        this.lite = lite;
        this.loggingLevel = loggingLevel;
        this.maxBufferSize = maxBufferSize;
        this.idleFlushingFrequencyMs = idleFlushingFrequencyMs;
        this.textChangeFlushingFrequencyMs = textChangeFlushingFrequencyMs;
        this.logHistorySize = logHistorySize;
        this.whitelistedComponents = whitelistedComponents;
    }

    public static ContentCaptureOptions forWhitelistingItself() {
        final ActivityThread at = ActivityThread.currentActivityThread();
        if (at == null) {
            throw new IllegalStateException("No ActivityThread");
        }

        final String packageName = at.getApplication().getPackageName();

        if (!"android.contentcaptureservice.cts".equals(packageName)) {
            Log.e(TAG, "forWhitelistingItself(): called by " + packageName);
            throw new SecurityException("Thou shall not pass!");
        }

        final ContentCaptureOptions options =
                new ContentCaptureOptions(/* whitelistedComponents= */ null);
        // Always log, as it's used by test only
        Log.i(TAG, "forWhitelistingItself(" + packageName + "): " + options);

        return options;
    }

    /** @hide */
    @VisibleForTesting
    public boolean isWhitelisted(@NonNull Context context) {
        if (whitelistedComponents == null) return true; // whole package is whitelisted
        final ContentCaptureClient client = context.getContentCaptureClient();
        if (client == null) {
            // Shouldn't happen, but it doesn't hurt to check...
            Log.w(TAG, "isWhitelisted(): no ContentCaptureClient on " + context);
            return false;
        }
        return whitelistedComponents.contains(client.contentCaptureClientGetComponentName());
    }

    @Override
    public String toString() {
        if (lite) {
            return "ContentCaptureOptions [loggingLevel=" + loggingLevel + " (lite)]";
        }
        final StringBuilder string = new StringBuilder("ContentCaptureOptions [");
        string.append("loggingLevel=").append(loggingLevel)
            .append(", maxBufferSize=").append(maxBufferSize)
            .append(", idleFlushingFrequencyMs=").append(idleFlushingFrequencyMs)
            .append(", textChangeFlushingFrequencyMs=").append(textChangeFlushingFrequencyMs)
            .append(", logHistorySize=").append(logHistorySize);
        if (whitelistedComponents != null) {
            string.append(", whitelisted=").append(whitelistedComponents);
        }
        return string.append(']').toString();
    }

    /** @hide */
    public void dumpShort(@NonNull PrintWriter pw) {
        pw.print("logLvl="); pw.print(loggingLevel);
        if (lite) {
            pw.print(", lite");
            return;
        }
        pw.print(", bufferSize="); pw.print(maxBufferSize);
        pw.print(", idle="); pw.print(idleFlushingFrequencyMs);
        pw.print(", textIdle="); pw.print(textChangeFlushingFrequencyMs);
        pw.print(", logSize="); pw.print(logHistorySize);
        if (whitelistedComponents != null) {
            pw.print(", whitelisted="); pw.print(whitelistedComponents);
        }
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeBoolean(lite);
        parcel.writeInt(loggingLevel);
        if (lite) return;

        parcel.writeInt(maxBufferSize);
        parcel.writeInt(idleFlushingFrequencyMs);
        parcel.writeInt(textChangeFlushingFrequencyMs);
        parcel.writeInt(logHistorySize);
        parcel.writeArraySet(whitelistedComponents);
    }

    public static final @android.annotation.NonNull Parcelable.Creator<ContentCaptureOptions> CREATOR =
            new Parcelable.Creator<ContentCaptureOptions>() {

                @Override
                public ContentCaptureOptions createFromParcel(Parcel parcel) {
                    final boolean lite = parcel.readBoolean();
                    final int loggingLevel = parcel.readInt();
                    if (lite) {
                        return new ContentCaptureOptions(loggingLevel);
                    }
                    final int maxBufferSize = parcel.readInt();
                    final int idleFlushingFrequencyMs = parcel.readInt();
                    final int textChangeFlushingFrequencyMs = parcel.readInt();
                    final int logHistorySize = parcel.readInt();
                    @SuppressWarnings("unchecked")
                    final ArraySet<ComponentName> whitelistedComponents =
                            (ArraySet<ComponentName>) parcel.readArraySet(null);
                    return new ContentCaptureOptions(loggingLevel, maxBufferSize,
                            idleFlushingFrequencyMs, textChangeFlushingFrequencyMs, logHistorySize,
                            whitelistedComponents);
                }

                @Override
                public ContentCaptureOptions[] newArray(int size) {
                    return new ContentCaptureOptions[size];
                }
    };
}
