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

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import android.util.Size;

import com.android.internal.graphics.ColorUtils;
import com.android.internal.graphics.palette.Palette;
import com.android.internal.graphics.palette.VariationalKMeansQuantizer;
import com.android.internal.util.ContrastColorUtil;

import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Provides information about the colors of a wallpaper.
 * <p>
 * Exposes the 3 most visually representative colors of a wallpaper. Can be either
 * {@link WallpaperColors#getPrimaryColor()}, {@link WallpaperColors#getSecondaryColor()}
 * or {@link WallpaperColors#getTertiaryColor()}.
 */
public final class WallpaperColors implements Parcelable {

    private static final boolean DEBUG_DARK_PIXELS = false;

    /**
     * Specifies that dark text is preferred over the current wallpaper for best presentation.
     * <p>
     * eg. A launcher may set its text color to black if this flag is specified.
     * @hide
     */
    @SystemApi
    public static final int HINT_SUPPORTS_DARK_TEXT = 1 << 0;

    /**
     * Specifies that dark theme is preferred over the current wallpaper for best presentation.
     * <p>
     * eg. A launcher may set its drawer color to black if this flag is specified.
     * @hide
     */
    @SystemApi
    public static final int HINT_SUPPORTS_DARK_THEME = 1 << 1;

    /**
     * Specifies that this object was generated by extracting colors from a bitmap.
     * @hide
     */
    public static final int HINT_FROM_BITMAP = 1 << 2;

    // Maximum size that a bitmap can have to keep our calculations sane
    private static final int MAX_BITMAP_SIZE = 112;

    // Even though we have a maximum size, we'll mainly match bitmap sizes
    // using the area instead. This way our comparisons are aspect ratio independent.
    private static final int MAX_WALLPAPER_EXTRACTION_AREA = MAX_BITMAP_SIZE * MAX_BITMAP_SIZE;

    // When extracting the main colors, only consider colors
    // present in at least MIN_COLOR_OCCURRENCE of the image
    private static final float MIN_COLOR_OCCURRENCE = 0.05f;

    // Decides when dark theme is optimal for this wallpaper
    private static final float DARK_THEME_MEAN_LUMINANCE = 0.25f;
    // Minimum mean luminosity that an image needs to have to support dark text
    private static final float BRIGHT_IMAGE_MEAN_LUMINANCE = 0.75f;
    // We also check if the image has dark pixels in it,
    // to avoid bright images with some dark spots.
    private static final float DARK_PIXEL_CONTRAST = 6f;
    private static final float MAX_DARK_AREA = 0.025f;

    private final ArrayList<Color> mMainColors;
    private int mColorHints;

    public WallpaperColors(Parcel parcel) {
        mMainColors = new ArrayList<>();
        final int count = parcel.readInt();
        for (int i = 0; i < count; i++) {
            final int colorInt = parcel.readInt();
            Color color = Color.valueOf(colorInt);
            mMainColors.add(color);
        }
        mColorHints = parcel.readInt();
    }

    /**
     * Constructs {@link WallpaperColors} from a drawable.
     * <p>
     * Main colors will be extracted from the drawable.
     *
     * @param drawable Source where to extract from.
     */
    public static WallpaperColors fromDrawable(Drawable drawable) {
        if (drawable == null) {
            throw new IllegalArgumentException("Drawable cannot be null");
        }

        Rect initialBounds = drawable.copyBounds();
        int width = drawable.getIntrinsicWidth();
        int height = drawable.getIntrinsicHeight();

        // Some drawables do not have intrinsic dimensions
        if (width <= 0 || height <= 0) {
            width = MAX_BITMAP_SIZE;
            height = MAX_BITMAP_SIZE;
        }

        Size optimalSize = calculateOptimalSize(width, height);
        Bitmap bitmap = Bitmap.createBitmap(optimalSize.getWidth(), optimalSize.getHeight(),
                Bitmap.Config.ARGB_8888);
        final Canvas bmpCanvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
        drawable.draw(bmpCanvas);

        final WallpaperColors colors = WallpaperColors.fromBitmap(bitmap);
        bitmap.recycle();

        drawable.setBounds(initialBounds);
        return colors;
    }

    /**
     * Constructs {@link WallpaperColors} from a bitmap.
     * <p>
     * Main colors will be extracted from the bitmap.
     *
     * @param bitmap Source where to extract from.
     */
    public static WallpaperColors fromBitmap(@NonNull Bitmap bitmap) {
        if (bitmap == null) {
            throw new IllegalArgumentException("Bitmap can't be null");
        }

        final int bitmapArea = bitmap.getWidth() * bitmap.getHeight();
        boolean shouldRecycle = false;
        if (bitmapArea > MAX_WALLPAPER_EXTRACTION_AREA) {
            shouldRecycle = true;
            Size optimalSize = calculateOptimalSize(bitmap.getWidth(), bitmap.getHeight());
            bitmap = Bitmap.createScaledBitmap(bitmap, optimalSize.getWidth(),
                    optimalSize.getHeight(), true /* filter */);
        }

        final Palette palette = Palette
                .from(bitmap)
                .setQuantizer(new VariationalKMeansQuantizer())
                .maximumColorCount(5)
                .clearFilters()
                .resizeBitmapArea(MAX_WALLPAPER_EXTRACTION_AREA)
                .generate();

        // Remove insignificant colors and sort swatches by population
        final ArrayList<Palette.Swatch> swatches = new ArrayList<>(palette.getSwatches());
        final float minColorArea = bitmap.getWidth() * bitmap.getHeight() * MIN_COLOR_OCCURRENCE;
        swatches.removeIf(s -> s.getPopulation() < minColorArea);
        swatches.sort((a, b) -> b.getPopulation() - a.getPopulation());

        final int swatchesSize = swatches.size();
        Color primary = null, secondary = null, tertiary = null;

        swatchLoop:
        for (int i = 0; i < swatchesSize; i++) {
            Color color = Color.valueOf(swatches.get(i).getRgb());
            switch (i) {
                case 0:
                    primary = color;
                    break;
                case 1:
                    secondary = color;
                    break;
                case 2:
                    tertiary = color;
                    break;
                default:
                    // out of bounds
                    break swatchLoop;
            }
        }

        int hints = calculateDarkHints(bitmap);

        if (shouldRecycle) {
            bitmap.recycle();
        }

        return new WallpaperColors(primary, secondary, tertiary, HINT_FROM_BITMAP | hints);
    }

    /**
     * Constructs a new object from three colors.
     *
     * @param primaryColor Primary color.
     * @param secondaryColor Secondary color.
     * @param tertiaryColor Tertiary color.
     * @see WallpaperColors#fromBitmap(Bitmap)
     * @see WallpaperColors#fromDrawable(Drawable)
     */
    public WallpaperColors(@NonNull Color primaryColor, @Nullable Color secondaryColor,
            @Nullable Color tertiaryColor) {
        this(primaryColor, secondaryColor, tertiaryColor, 0);
    }

    /**
     * Constructs a new object from three colors, where hints can be specified.
     *
     * @param primaryColor Primary color.
     * @param secondaryColor Secondary color.
     * @param tertiaryColor Tertiary color.
     * @param colorHints A combination of WallpaperColor hints.
     * @see WallpaperColors#HINT_SUPPORTS_DARK_TEXT
     * @see WallpaperColors#fromBitmap(Bitmap)
     * @see WallpaperColors#fromDrawable(Drawable)
     * @hide
     */
    @SystemApi
    public WallpaperColors(@NonNull Color primaryColor, @Nullable Color secondaryColor,
            @Nullable Color tertiaryColor, int colorHints) {

        if (primaryColor == null) {
            throw new IllegalArgumentException("Primary color should never be null.");
        }

        mMainColors = new ArrayList<>(3);
        mMainColors.add(primaryColor);
        if (secondaryColor != null) {
            mMainColors.add(secondaryColor);
        }
        if (tertiaryColor != null) {
            if (secondaryColor == null) {
                throw new IllegalArgumentException("tertiaryColor can't be specified when "
                        + "secondaryColor is null");
            }
            mMainColors.add(tertiaryColor);
        }

        mColorHints = colorHints;
    }

    public static final @android.annotation.NonNull Creator<WallpaperColors> CREATOR = new Creator<WallpaperColors>() {
        @Override
        public WallpaperColors createFromParcel(Parcel in) {
            return new WallpaperColors(in);
        }

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

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        List<Color> mainColors = getMainColors();
        int count = mainColors.size();
        dest.writeInt(count);
        for (int i = 0; i < count; i++) {
            Color color = mainColors.get(i);
            dest.writeInt(color.toArgb());
        }
        dest.writeInt(mColorHints);
    }

    /**
     * Gets the most visually representative color of the wallpaper.
     * "Visually representative" means easily noticeable in the image,
     * probably happening at high frequency.
     *
     * @return A color.
     */
    public @NonNull Color getPrimaryColor() {
        return mMainColors.get(0);
    }

    /**
     * Gets the second most preeminent color of the wallpaper. Can be null.
     *
     * @return A color, may be null.
     */
    public @Nullable Color getSecondaryColor() {
        return mMainColors.size() < 2 ? null : mMainColors.get(1);
    }

    /**
     * Gets the third most preeminent color of the wallpaper. Can be null.
     *
     * @return A color, may be null.
     */
    public @Nullable Color getTertiaryColor() {
        return mMainColors.size() < 3 ? null : mMainColors.get(2);
    }

    /**
     * List of most preeminent colors, sorted by importance.
     *
     * @return List of colors.
     * @hide
     */
    public @NonNull List<Color> getMainColors() {
        return Collections.unmodifiableList(mMainColors);
    }

    @Override
    public boolean equals(Object o) {
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        WallpaperColors other = (WallpaperColors) o;
        return mMainColors.equals(other.mMainColors)
                && mColorHints == other.mColorHints;
    }

    @Override
    public int hashCode() {
        return 31 * mMainColors.hashCode() + mColorHints;
    }

    /**
     * Combination of WallpaperColor hints.
     *
     * @see WallpaperColors#HINT_SUPPORTS_DARK_TEXT
     * @return True if dark text is supported.
     * @hide
     */
    @SystemApi
    public int getColorHints() {
        return mColorHints;
    }

    /**
     * @param colorHints Combination of WallpaperColors hints.
     * @see WallpaperColors#HINT_SUPPORTS_DARK_TEXT
     * @hide
     */
    public void setColorHints(int colorHints) {
        mColorHints = colorHints;
    }

    /**
     * Checks if image is bright and clean enough to support light text.
     *
     * @param source What to read.
     * @return Whether image supports dark text or not.
     */
    private static int calculateDarkHints(Bitmap source) {
        if (source == null) {
            return 0;
        }

        int[] pixels = new int[source.getWidth() * source.getHeight()];
        double totalLuminance = 0;
        final int maxDarkPixels = (int) (pixels.length * MAX_DARK_AREA);
        int darkPixels = 0;
        source.getPixels(pixels, 0 /* offset */, source.getWidth(), 0 /* x */, 0 /* y */,
                source.getWidth(), source.getHeight());

        // This bitmap was already resized to fit the maximum allowed area.
        // Let's just loop through the pixels, no sweat!
        float[] tmpHsl = new float[3];
        for (int i = 0; i < pixels.length; i++) {
            ColorUtils.colorToHSL(pixels[i], tmpHsl);
            final float luminance = tmpHsl[2];
            final int alpha = Color.alpha(pixels[i]);
            // Make sure we don't have a dark pixel mass that will
            // make text illegible.
            final boolean satisfiesTextContrast = ContrastColorUtil
                    .calculateContrast(pixels[i], Color.BLACK) > DARK_PIXEL_CONTRAST;
            if (!satisfiesTextContrast && alpha != 0) {
                darkPixels++;
                if (DEBUG_DARK_PIXELS) {
                    pixels[i] = Color.RED;
                }
            }
            totalLuminance += luminance;
        }

        int hints = 0;
        double meanLuminance = totalLuminance / pixels.length;
        if (meanLuminance > BRIGHT_IMAGE_MEAN_LUMINANCE && darkPixels < maxDarkPixels) {
            hints |= HINT_SUPPORTS_DARK_TEXT;
        }
        if (meanLuminance < DARK_THEME_MEAN_LUMINANCE) {
            hints |= HINT_SUPPORTS_DARK_THEME;
        }

        if (DEBUG_DARK_PIXELS) {
            try (FileOutputStream out = new FileOutputStream("/data/pixels.png")) {
                source.setPixels(pixels, 0, source.getWidth(), 0, 0, source.getWidth(),
                        source.getHeight());
                source.compress(Bitmap.CompressFormat.PNG, 100, out);
            } catch (Exception e) {
                e.printStackTrace();
            }
            Log.d("WallpaperColors", "l: " + meanLuminance + ", d: " + darkPixels +
                    " maxD: " + maxDarkPixels + " numPixels: " + pixels.length);
        }

        return hints;
    }

    private static Size calculateOptimalSize(int width, int height) {
        // Calculate how big the bitmap needs to be.
        // This avoids unnecessary processing and allocation inside Palette.
        final int requestedArea = width * height;
        double scale = 1;
        if (requestedArea > MAX_WALLPAPER_EXTRACTION_AREA) {
            scale = Math.sqrt(MAX_WALLPAPER_EXTRACTION_AREA / (double) requestedArea);
        }
        int newWidth = (int) (width * scale);
        int newHeight = (int) (height * scale);
        // Dealing with edge cases of the drawable being too wide or too tall.
        // Width or height would end up being 0, in this case we'll set it to 1.
        if (newWidth == 0) {
            newWidth = 1;
        }
        if (newHeight == 0) {
            newHeight = 1;
        }

        return new Size(newWidth, newHeight);
    }

    @Override
    public String toString() {
        final StringBuilder colors = new StringBuilder();
        for (int i = 0; i < mMainColors.size(); i++) {
            colors.append(Integer.toHexString(mMainColors.get(i).toArgb())).append(" ");
        }
        return "[WallpaperColors: " + colors.toString() + "h: " + mColorHints + "]";
    }
}
