/*
 * 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.internal.widget;

import android.annotation.DrawableRes;
import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.ImageDecoder;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import android.util.Size;

import com.android.internal.annotations.VisibleForTesting;

import java.io.IOException;

/** A class to extract Drawables from a MessagingStyle/ConversationStyle message. */
public class LocalImageResolver {

    private static final String TAG = "LocalImageResolver";

    /** There's no max size specified, load at original size. */
    public static final int NO_MAX_SIZE = -1;

    @VisibleForTesting
    static final int DEFAULT_MAX_SAFE_ICON_SIZE_PX = 480;

    /**
     * Resolve an image from the given Uri using {@link ImageDecoder} if it contains a
     * bitmap reference.
     * Negative or zero dimensions will result in icon loaded in its original size.
     *
     * @throws IOException if the icon could not be loaded.
     */
    @Nullable
    public static Drawable resolveImage(Uri uri, Context context) throws IOException {
        try {
            final ImageDecoder.Source source =
                    ImageDecoder.createSource(context.getContentResolver(), uri);
            return ImageDecoder.decodeDrawable(source,
                    (decoder, info, s) -> LocalImageResolver.onHeaderDecoded(decoder, info,
                            DEFAULT_MAX_SAFE_ICON_SIZE_PX, DEFAULT_MAX_SAFE_ICON_SIZE_PX));
        } catch (Exception e) {
            // Invalid drawable resource can actually throw either NullPointerException or
            // ResourceNotFoundException. This sanitizes to expected output.
            throw new IOException(e);
        }
    }

    /**
     * Get the drawable from Icon using {@link ImageDecoder} if it contains a bitmap reference, or
     * using {@link Icon#loadDrawable(Context)} otherwise.  This will correctly apply the Icon's,
     * tint, if present, to the drawable.
     * Negative or zero dimensions will result in icon loaded in its original size.
     *
     * @return drawable or null if the passed icon parameter was null.
     * @throws IOException if the icon could not be loaded.
     */
    @Nullable
    public static Drawable resolveImage(@Nullable Icon icon, Context context) throws IOException {
        return resolveImage(icon, context, DEFAULT_MAX_SAFE_ICON_SIZE_PX,
                DEFAULT_MAX_SAFE_ICON_SIZE_PX);
    }

    /**
     * Get the drawable from Icon using {@link ImageDecoder} if it contains a bitmap reference, or
     * using {@link Icon#loadDrawable(Context)} otherwise.  This will correctly apply the Icon's,
     * tint, if present, to the drawable.
     * Negative or zero dimensions will result in icon loaded in its original size.
     *
     * @return loaded icon or null if a null icon was passed as a parameter.
     * @throws IOException if the icon could not be loaded.
     */
    @Nullable
    public static Drawable resolveImage(@Nullable Icon icon, Context context, int maxWidth,
            int maxHeight) {
        if (icon == null) {
            return null;
        }

        switch (icon.getType()) {
            case Icon.TYPE_URI:
            case Icon.TYPE_URI_ADAPTIVE_BITMAP:
                Uri uri = getResolvableUri(icon);
                if (uri != null) {
                    Drawable result = resolveImage(uri, context, maxWidth, maxHeight);
                    if (result != null) {
                        return tintDrawable(icon, result);
                    }
                }
                break;
            case Icon.TYPE_RESOURCE:
                Resources res = resolveResourcesForIcon(context, icon);
                if (res == null) {
                    // We couldn't resolve resources properly, fall back to icon loading.
                    return icon.loadDrawable(context);
                }

                Drawable result = resolveImage(res, icon.getResId(), maxWidth, maxHeight);
                if (result != null) {
                    return tintDrawable(icon, result);
                }
                break;
            case Icon.TYPE_BITMAP:
            case Icon.TYPE_ADAPTIVE_BITMAP:
                return resolveBitmapImage(icon, context, maxWidth, maxHeight);
            case Icon.TYPE_DATA:    // We can't really improve on raw data images.
            default:
                break;
        }

        // Fallback to straight drawable load if we fail with more efficient approach.
        try {
            return icon.loadDrawable(context);
        } catch (Resources.NotFoundException e) {
            return null;
        }
    }

    /**
     * Attempts to resolve the resource as a bitmap drawable constrained within max sizes.
     */
    @Nullable
    public static Drawable resolveImage(Uri uri, Context context, int maxWidth, int maxHeight) {
        final ImageDecoder.Source source =
                ImageDecoder.createSource(context.getContentResolver(), uri);
        return resolveImage(source, maxWidth, maxHeight);
    }

    /**
     * Attempts to resolve the resource as a bitmap drawable constrained within max sizes.
     *
     * @return decoded drawable or null if the passed resource is not a straight bitmap
     */
    @Nullable
    public static Drawable resolveImage(@DrawableRes int resId, Context context, int maxWidth,
            int maxHeight) {
        final ImageDecoder.Source source = ImageDecoder.createSource(context.getResources(), resId);
        return resolveImage(source, maxWidth, maxHeight);
    }

    @Nullable
    private static Drawable resolveImage(Resources res, @DrawableRes int resId, int maxWidth,
            int maxHeight) {
        final ImageDecoder.Source source = ImageDecoder.createSource(res, resId);
        return resolveImage(source, maxWidth, maxHeight);
    }

    @Nullable
    private static Drawable resolveBitmapImage(Icon icon, Context context, int maxWidth,
            int maxHeight) {

        if (maxWidth > 0 && maxHeight > 0) {
            Bitmap bitmap = icon.getBitmap();
            if (bitmap == null) {
                return null;
            }

            if (bitmap.getWidth() > maxWidth || bitmap.getHeight() > maxHeight) {
                Icon smallerIcon = icon.getType() == Icon.TYPE_ADAPTIVE_BITMAP
                        ? Icon.createWithAdaptiveBitmap(bitmap) : Icon.createWithBitmap(bitmap);
                // We don't want to modify the source icon, create a copy.
                smallerIcon.setTintList(icon.getTintList())
                        .setTintBlendMode(icon.getTintBlendMode())
                        .scaleDownIfNecessary(maxWidth, maxHeight);
                return smallerIcon.loadDrawable(context);
            }
        }

        return icon.loadDrawable(context);
    }

    @Nullable
    private static Drawable tintDrawable(Icon icon, @Nullable Drawable drawable) {
        if (drawable == null) {
            return null;
        }

        if (icon.hasTint()) {
            drawable.mutate();
            drawable.setTintList(icon.getTintList());
            drawable.setTintBlendMode(icon.getTintBlendMode());
        }

        return drawable;
    }

    private static Drawable resolveImage(ImageDecoder.Source source, int maxWidth, int maxHeight) {
        try {
            return ImageDecoder.decodeDrawable(source, (decoder, info, unused) -> {
                if (maxWidth <= 0 || maxHeight <= 0) {
                    return;
                }

                final Size size = info.getSize();
                if (size.getWidth() <= maxWidth && size.getHeight() <= maxHeight) {
                    // We don't want to upscale images needlessly.
                    return;
                }

                if (size.getWidth() > size.getHeight()) {
                    if (size.getWidth() > maxWidth) {
                        final int targetHeight = size.getHeight() * maxWidth / size.getWidth();
                        decoder.setTargetSize(maxWidth, targetHeight);
                    }
                } else {
                    if (size.getHeight() > maxHeight) {
                        final int targetWidth = size.getWidth() * maxHeight / size.getHeight();
                        decoder.setTargetSize(targetWidth, maxHeight);
                    }
                }
            });

        // ImageDecoder documentation is misleading a bit - it'll throw NotFoundException
        // in some cases despite it not saying so. Rethrow it as an IOException to keep
        // our API contract.
        } catch (IOException | Resources.NotFoundException e) {
            Log.d(TAG, "Couldn't use ImageDecoder for drawable, falling back to non-resized load.");
            return null;
        }
    }

    private static int getPowerOfTwoForSampleRatio(double ratio) {
        final int k = Integer.highestOneBit((int) Math.floor(ratio));
        return Math.max(1, k);
    }

    private static void onHeaderDecoded(ImageDecoder decoder, ImageDecoder.ImageInfo info,
            int maxWidth, int maxHeight) {
        final Size size = info.getSize();
        final int originalSize = Math.max(size.getHeight(), size.getWidth());
        final int maxSize = Math.max(maxWidth, maxHeight);
        final double ratio = (originalSize > maxSize)
                ? originalSize * 1f / maxSize
                : 1.0;
        decoder.setTargetSampleSize(getPowerOfTwoForSampleRatio(ratio));
    }

    /**
     * Gets the Uri for this icon, assuming the icon can be treated as a pure Uri.  Null otherwise.
     */
    @Nullable
    private static Uri getResolvableUri(@Nullable Icon icon) {
        if (icon == null || (icon.getType() != Icon.TYPE_URI
                && icon.getType() != Icon.TYPE_URI_ADAPTIVE_BITMAP)) {
            return null;
        }
        return icon.getUri();
    }

    /**
     * Resolves the correct resources package for a given Icon - it may come from another
     * package.
     *
     * @see Icon#loadDrawableInner(Context)
     * @hide
     *
     * @return resources instance if the operation succeeded, null otherwise
     */
    @Nullable
    @VisibleForTesting
    public static Resources resolveResourcesForIcon(Context context, Icon icon) {
        if (icon.getType() != Icon.TYPE_RESOURCE) {
            return null;
        }

        // Icons cache resolved resources, use cache if available.
        Resources res = icon.getResources();
        if (res != null) {
            return res;
        }

        String resPackage = icon.getResPackage();
        // No package means we try to use current context.
        if (TextUtils.isEmpty(resPackage) || context.getPackageName().equals(resPackage)) {
            return context.getResources();
        }

        if ("android".equals(resPackage)) {
            return Resources.getSystem();
        }

        final PackageManager pm = context.getPackageManager();
        try {
            ApplicationInfo ai = pm.getApplicationInfo(resPackage,
                    PackageManager.MATCH_UNINSTALLED_PACKAGES
                            | PackageManager.GET_SHARED_LIBRARY_FILES);
            if (ai != null) {
                return pm.getResourcesForApplication(ai);
            }
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG, String.format("Unable to resolve package %s for icon %s", resPackage, icon));
            return null;
        }

        return null;
    }
}
