/*
 * 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 com.android.internal.colorextraction;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.WallpaperColors;
import android.app.WallpaperManager;
import android.content.Context;
import android.os.Trace;
import android.os.UserHandle;
import android.util.Log;
import android.util.SparseArray;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.colorextraction.types.ExtractionType;
import com.android.internal.colorextraction.types.Tonal;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;

/**
 * Class to process wallpaper colors and generate a tonal palette based on them.
 */
public class ColorExtractor implements WallpaperManager.OnColorsChangedListener {

    public static final int TYPE_NORMAL = 0;
    public static final int TYPE_DARK = 1;
    public static final int TYPE_EXTRA_DARK = 2;
    private static final int[] sGradientTypes = new int[]{TYPE_NORMAL, TYPE_DARK, TYPE_EXTRA_DARK};

    private static final String TAG = "ColorExtractor";
    private static final boolean DEBUG = false;

    protected final SparseArray<GradientColors[]> mGradientColors;
    private final ArrayList<WeakReference<OnColorsChangedListener>> mOnColorsChangedListeners;
    private final Context mContext;
    private final ExtractionType mExtractionType;
    protected WallpaperColors mSystemColors;
    protected WallpaperColors mLockColors;

    public ColorExtractor(Context context) {
        this(context, new Tonal(context));
    }

    @VisibleForTesting
    public ColorExtractor(Context context, ExtractionType extractionType) {
        mContext = context;
        mExtractionType = extractionType;

        mGradientColors = new SparseArray<>();
        for (int which : new int[] { WallpaperManager.FLAG_LOCK, WallpaperManager.FLAG_SYSTEM}) {
            GradientColors[] colors = new GradientColors[sGradientTypes.length];
            mGradientColors.append(which, colors);
            for (int type : sGradientTypes) {
                colors[type] = new GradientColors();
            }
        }

        mOnColorsChangedListeners = new ArrayList<>();
        GradientColors[] systemColors = mGradientColors.get(WallpaperManager.FLAG_SYSTEM);
        GradientColors[] lockColors = mGradientColors.get(WallpaperManager.FLAG_LOCK);

        WallpaperManager wallpaperManager = mContext.getSystemService(WallpaperManager.class);
        if (wallpaperManager == null) {
            Log.w(TAG, "Can't listen to color changes!");
        } else {
            wallpaperManager.addOnColorsChangedListener(this, null /* handler */);

            // Initialize all gradients with the current colors
            Trace.beginSection("ColorExtractor#getWallpaperColors");
            mSystemColors = wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
            mLockColors = wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_LOCK);
            Trace.endSection();
        }

        // Initialize all gradients with the current colors
        extractInto(mSystemColors,
                systemColors[TYPE_NORMAL],
                systemColors[TYPE_DARK],
                systemColors[TYPE_EXTRA_DARK]);
        extractInto(mLockColors,
                lockColors[TYPE_NORMAL],
                lockColors[TYPE_DARK],
                lockColors[TYPE_EXTRA_DARK]);
    }

    /**
     * Retrieve gradient colors for a specific wallpaper.
     *
     * @param which FLAG_LOCK or FLAG_SYSTEM
     * @return colors
     */
    @NonNull
    public GradientColors getColors(int which) {
        return getColors(which, TYPE_DARK);
    }

    /**
     * Get current gradient colors for one of the possible gradient types
     *
     * @param which FLAG_LOCK or FLAG_SYSTEM
     * @param type TYPE_NORMAL, TYPE_DARK or TYPE_EXTRA_DARK
     * @return colors
     */
    @NonNull
    public GradientColors getColors(int which, int type) {
        if (type != TYPE_NORMAL && type != TYPE_DARK && type != TYPE_EXTRA_DARK) {
            throw new IllegalArgumentException(
                    "type should be TYPE_NORMAL, TYPE_DARK or TYPE_EXTRA_DARK");
        }
        if (which != WallpaperManager.FLAG_LOCK && which != WallpaperManager.FLAG_SYSTEM) {
            throw new IllegalArgumentException("which should be FLAG_SYSTEM or FLAG_NORMAL");
        }
        return mGradientColors.get(which)[type];
    }

    /**
     * Get the last available WallpaperColors without forcing new extraction.
     *
     * @param which FLAG_LOCK or FLAG_SYSTEM
     * @return Last cached colors
     */
    @Nullable
    public WallpaperColors getWallpaperColors(int which) {
        if (which == WallpaperManager.FLAG_LOCK) {
            return mLockColors;
        } else if (which == WallpaperManager.FLAG_SYSTEM) {
            return mSystemColors;
        } else {
            throw new IllegalArgumentException("Invalid value for which: " + which);
        }
    }

    @Override
    public void onColorsChanged(WallpaperColors colors, int which) {
        if (DEBUG) {
            Log.d(TAG, "New wallpaper colors for " + which + ": " + colors);
        }
        boolean changed = false;
        if ((which & WallpaperManager.FLAG_LOCK) != 0) {
            mLockColors = colors;
            GradientColors[] lockColors = mGradientColors.get(WallpaperManager.FLAG_LOCK);
            extractInto(colors, lockColors[TYPE_NORMAL], lockColors[TYPE_DARK],
                    lockColors[TYPE_EXTRA_DARK]);
            changed = true;
        }
        if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
            mSystemColors = colors;
            GradientColors[] systemColors = mGradientColors.get(WallpaperManager.FLAG_SYSTEM);
            extractInto(colors, systemColors[TYPE_NORMAL], systemColors[TYPE_DARK],
                    systemColors[TYPE_EXTRA_DARK]);
            changed = true;
        }

        if (changed) {
            triggerColorsChanged(which);
        }
    }

    protected void triggerColorsChanged(int which) {
        ArrayList<WeakReference<OnColorsChangedListener>> references =
                new ArrayList<>(mOnColorsChangedListeners);
        final int size = references.size();
        for (int i = 0; i < size; i++) {
            final WeakReference<OnColorsChangedListener> weakReference = references.get(i);
            final OnColorsChangedListener listener = weakReference.get();
            if (listener == null) {
                mOnColorsChangedListeners.remove(weakReference);
            } else {
                listener.onColorsChanged(this, which);
            }
        }
    }

    private void extractInto(WallpaperColors inWallpaperColors,
            GradientColors outGradientColorsNormal, GradientColors outGradientColorsDark,
            GradientColors outGradientColorsExtraDark) {
        mExtractionType.extractInto(inWallpaperColors, outGradientColorsNormal,
                outGradientColorsDark, outGradientColorsExtraDark);
    }

    public void destroy() {
        WallpaperManager wallpaperManager = mContext.getSystemService(WallpaperManager.class);
        if (wallpaperManager != null) {
            wallpaperManager.removeOnColorsChangedListener(this);
        }
    }

    public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener) {
        mOnColorsChangedListeners.add(new WeakReference<>(listener));
    }

    public void removeOnColorsChangedListener(@NonNull OnColorsChangedListener listener) {
        ArrayList<WeakReference<OnColorsChangedListener>> references =
                new ArrayList<>(mOnColorsChangedListeners);
        final int size = references.size();
        for (int i = 0; i < size; i++) {
            final WeakReference<OnColorsChangedListener> weakReference = references.get(i);
            if (weakReference.get() == listener) {
                mOnColorsChangedListeners.remove(weakReference);
                break;
            }
        }
    }

    public static class GradientColors {
        private int mMainColor;
        private int mSecondaryColor;
        private boolean mSupportsDarkText;

        public void setMainColor(int mainColor) {
            mMainColor = mainColor;
        }

        public void setSecondaryColor(int secondaryColor) {
            mSecondaryColor = secondaryColor;
        }

        public void setSupportsDarkText(boolean supportsDarkText) {
            mSupportsDarkText = supportsDarkText;
        }

        public void set(GradientColors other) {
            mMainColor = other.mMainColor;
            mSecondaryColor = other.mSecondaryColor;
            mSupportsDarkText = other.mSupportsDarkText;
        }

        public int getMainColor() {
            return mMainColor;
        }

        public int getSecondaryColor() {
            return mSecondaryColor;
        }

        public boolean supportsDarkText() {
            return mSupportsDarkText;
        }

        @Override
        public boolean equals(Object o) {
            if (o == null || o.getClass() != getClass()) {
                return false;
            }
            GradientColors other = (GradientColors) o;
            return other.mMainColor == mMainColor &&
                    other.mSecondaryColor == mSecondaryColor &&
                    other.mSupportsDarkText == mSupportsDarkText;
        }

        @Override
        public int hashCode() {
            int code = mMainColor;
            code = 31 * code + mSecondaryColor;
            code = 31 * code + (mSupportsDarkText ? 0 : 1);
            return code;
        }

        @Override
        public String toString() {
            return "GradientColors(" + Integer.toHexString(mMainColor) + ", "
                    + Integer.toHexString(mSecondaryColor) + ")";
        }
    }

    public interface OnColorsChangedListener {
        void onColorsChanged(ColorExtractor colorExtractor, int which);
    }
}