/*
 * 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 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 + "]";
    }
}
