/*
 * Copyright (C) 2017 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.pm;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.Intent;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;

/**
 * Describes an externally resolvable instant application. There are three states that this class
 * can represent: <p/>
 * <ul>
 *     <li>
 *         The first, usable only for non http/s intents, implies that the resolver cannot
 *         immediately resolve this intent and would prefer that resolution be deferred to the
 *         instant app installer. Represent this state with {@link #InstantAppResolveInfo(Bundle)}.
 *         If the {@link android.content.Intent} has the scheme set to http/s and a set of digest
 *         prefixes were passed into one of the resolve methods in
 *         {@link android.app.InstantAppResolverService}, this state cannot be used.
 *     </li>
 *     <li>
 *         The second represents a partial match and is constructed with any of the other
 *         constructors. By setting one or more of the {@link Nullable}arguments to null, you
 *         communicate to the resolver in response to
 *         {@link android.app.InstantAppResolverService#onGetInstantAppResolveInfo(Intent, int[],
 *                String, InstantAppResolverService.InstantAppResolutionCallback)}
 *         that you need a 2nd round of resolution to complete the request.
 *     </li>
 *     <li>
 *         The third represents a complete match and is constructed with all @Nullable parameters
 *         populated.
 *     </li>
 * </ul>
 * @hide
 */
@SystemApi
public final class InstantAppResolveInfo implements Parcelable {
    /** Algorithm that will be used to generate the domain digest */
    private static final String SHA_ALGORITHM = "SHA-256";

    private static final byte[] EMPTY_DIGEST = new byte[0];

    private final InstantAppDigest mDigest;
    private final String mPackageName;
    /** The filters used to match domain */
    private final List<InstantAppIntentFilter> mFilters;
    /** The version code of the app that this class resolves to */
    private final long mVersionCode;
    /** Data about the app that should be passed along to the Instant App installer on resolve */
    private final Bundle mExtras;
    /**
     * A flag that indicates that the resolver is aware that an app may match, but would prefer
     * that the installer get the sanitized intent to decide. This should not be used for
     * resolutions that include a host and will be ignored in such cases.
     */
    private final boolean mShouldLetInstallerDecide;

    /** Constructor for intent-based InstantApp resolution results. */
    public InstantAppResolveInfo(@NonNull InstantAppDigest digest, @Nullable String packageName,
            @Nullable List<InstantAppIntentFilter> filters, int versionCode) {
        this(digest, packageName, filters, (long) versionCode, null /* extras */);
    }

    /** Constructor for intent-based InstantApp resolution results with extras. */
    public InstantAppResolveInfo(@NonNull InstantAppDigest digest, @Nullable String packageName,
            @Nullable List<InstantAppIntentFilter> filters, long versionCode,
            @Nullable Bundle extras) {
        this(digest, packageName, filters, versionCode, extras, false);
    }

    /** Constructor for intent-based InstantApp resolution results with extras. */
    private InstantAppResolveInfo(@NonNull InstantAppDigest digest, @Nullable String packageName,
            @Nullable List<InstantAppIntentFilter> filters, long versionCode,
            @Nullable Bundle extras, boolean shouldLetInstallerDecide) {
        // validate arguments
        if ((packageName == null && (filters != null && filters.size() != 0))
                || (packageName != null && (filters == null || filters.size() == 0))) {
            throw new IllegalArgumentException();
        }
        mDigest = digest;
        if (filters != null) {
            mFilters = new ArrayList<>(filters.size());
            mFilters.addAll(filters);
        } else {
            mFilters = null;
        }
        mPackageName = packageName;
        mVersionCode = versionCode;
        mExtras = extras;
        mShouldLetInstallerDecide = shouldLetInstallerDecide;
    }

    /** Constructor for intent-based InstantApp resolution results by hostname. */
    public InstantAppResolveInfo(@NonNull String hostName, @Nullable String packageName,
            @Nullable List<InstantAppIntentFilter> filters) {
        this(new InstantAppDigest(hostName), packageName, filters, -1 /*versionCode*/,
                null /* extras */);
    }

    /**
     * Constructor that creates a "let the installer decide" response with optional included
     * extras.
     */
    public InstantAppResolveInfo(@Nullable Bundle extras) {
        this(InstantAppDigest.UNDEFINED, null, null, -1, extras, true);
    }

    InstantAppResolveInfo(Parcel in) {
        mShouldLetInstallerDecide = in.readBoolean();
        mExtras = in.readBundle();
        if (mShouldLetInstallerDecide) {
            mDigest = InstantAppDigest.UNDEFINED;
            mPackageName = null;
            mFilters = Collections.emptyList();
            mVersionCode = -1;
        } else {
            mDigest = in.readParcelable(null /*loader*/);
            mPackageName = in.readString();
            mFilters = new ArrayList<>();
            in.readList(mFilters, null /*loader*/);
            mVersionCode = in.readLong();
        }
    }

    /** Returns true if the installer should be notified that it should query for packages. */
    public boolean shouldLetInstallerDecide() {
        return mShouldLetInstallerDecide;
    }

    public byte[] getDigestBytes() {
        return mDigest.mDigestBytes.length > 0 ? mDigest.getDigestBytes()[0] : EMPTY_DIGEST;
    }

    public int getDigestPrefix() {
        return mDigest.getDigestPrefix()[0];
    }

    public String getPackageName() {
        return mPackageName;
    }

    public List<InstantAppIntentFilter> getIntentFilters() {
        return mFilters;
    }

    /**
     * @deprecated Use {@link #getLongVersionCode} instead.
     */
    @Deprecated
    public int getVersionCode() {
        return (int) (mVersionCode & 0xffffffff);
    }

    public long getLongVersionCode() {
        return mVersionCode;
    }

    @Nullable
    public Bundle getExtras() {
        return mExtras;
    }

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

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeBoolean(mShouldLetInstallerDecide);
        out.writeBundle(mExtras);
        if (mShouldLetInstallerDecide) {
            return;
        }
        out.writeParcelable(mDigest, flags);
        out.writeString(mPackageName);
        out.writeList(mFilters);
        out.writeLong(mVersionCode);
    }

    public static final Parcelable.Creator<InstantAppResolveInfo> CREATOR
            = new Parcelable.Creator<InstantAppResolveInfo>() {
        public InstantAppResolveInfo createFromParcel(Parcel in) {
            return new InstantAppResolveInfo(in);
        }

        public InstantAppResolveInfo[] newArray(int size) {
            return new InstantAppResolveInfo[size];
        }
    };

    /**
     * Helper class to generate and store each of the digests and prefixes
     * sent to the Instant App Resolver.
     * <p>
     * Since intent filters may want to handle multiple hosts within a
     * domain [eg “*.google.com”], the resolver is presented with multiple
     * hash prefixes. For example, "a.b.c.d.e" generates digests for
     * "d.e", "c.d.e", "b.c.d.e" and "a.b.c.d.e".
     *
     * @hide
     */
    @SystemApi
    public static final class InstantAppDigest implements Parcelable {
        private static final int DIGEST_MASK = 0xfffff000;

        public static final InstantAppDigest UNDEFINED =
                new InstantAppDigest(new byte[][]{}, new int[]{});
        /** Full digest of the domain hashes */
        private final byte[][] mDigestBytes;
        /** The first 4 bytes of the domain hashes */
        private final int[] mDigestPrefix;

        public InstantAppDigest(@NonNull String hostName) {
            this(hostName, -1 /*maxDigests*/);
        }

        /** @hide */
        public InstantAppDigest(@NonNull String hostName, int maxDigests) {
            if (hostName == null) {
                throw new IllegalArgumentException();
            }
            mDigestBytes = generateDigest(hostName.toLowerCase(Locale.ENGLISH), maxDigests);
            mDigestPrefix = new int[mDigestBytes.length];
            for (int i = 0; i < mDigestBytes.length; i++) {
                mDigestPrefix[i] =
                        ((mDigestBytes[i][0] & 0xFF) << 24
                                | (mDigestBytes[i][1] & 0xFF) << 16
                                | (mDigestBytes[i][2] & 0xFF) << 8
                                | (mDigestBytes[i][3] & 0xFF) << 0)
                        & DIGEST_MASK;
            }
        }

        private InstantAppDigest(byte[][] digestBytes, int[] prefix) {
            this.mDigestPrefix = prefix;
            this.mDigestBytes = digestBytes;
        }

        private static byte[][] generateDigest(String hostName, int maxDigests) {
            ArrayList<byte[]> digests = new ArrayList<>();
            try {
                final MessageDigest digest = MessageDigest.getInstance(SHA_ALGORITHM);
                if (maxDigests <= 0) {
                    final byte[] hostBytes = hostName.getBytes();
                    digests.add(digest.digest(hostBytes));
                } else {
                    int prevDot = hostName.lastIndexOf('.');
                    prevDot = hostName.lastIndexOf('.', prevDot - 1);
                    // shortcut for short URLs
                    if (prevDot < 0) {
                        digests.add(digest.digest(hostName.getBytes()));
                    } else {
                        byte[] hostBytes =
                                hostName.substring(prevDot + 1, hostName.length()).getBytes();
                        digests.add(digest.digest(hostBytes));
                        int digestCount = 1;
                        while (prevDot >= 0 && digestCount < maxDigests) {
                            prevDot = hostName.lastIndexOf('.', prevDot - 1);
                            hostBytes =
                                    hostName.substring(prevDot + 1, hostName.length()).getBytes();
                            digests.add(digest.digest(hostBytes));
                            digestCount++;
                        }
                    }
                }
            } catch (NoSuchAlgorithmException e) {
                throw new IllegalStateException("could not find digest algorithm");
            }
            return digests.toArray(new byte[digests.size()][]);
        }

        InstantAppDigest(Parcel in) {
            final int digestCount = in.readInt();
            if (digestCount == -1) {
                mDigestBytes = null;
            } else {
                mDigestBytes = new byte[digestCount][];
                for (int i = 0; i < digestCount; i++) {
                    mDigestBytes[i] = in.createByteArray();
                }
            }
            mDigestPrefix = in.createIntArray();
        }

        public byte[][] getDigestBytes() {
            return mDigestBytes;
        }

        public int[] getDigestPrefix() {
            return mDigestPrefix;
        }

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

        @Override
        public void writeToParcel(Parcel out, int flags) {
            if (mDigestBytes == null) {
                out.writeInt(-1);
            } else {
                out.writeInt(mDigestBytes.length);
                for (int i = 0; i < mDigestBytes.length; i++) {
                    out.writeByteArray(mDigestBytes[i]);
                }
            }
            out.writeIntArray(mDigestPrefix);
        }

        @SuppressWarnings("hiding")
        public static final Parcelable.Creator<InstantAppDigest> CREATOR =
                new Parcelable.Creator<InstantAppDigest>() {
            @Override
            public InstantAppDigest createFromParcel(Parcel in) {
                return new InstantAppDigest(in);
            }
            @Override
            public InstantAppDigest[] newArray(int size) {
                return new InstantAppDigest[size];
            }
        };
    }
}
