/FileExtraction/Java_unseen/PowerExplorer_PowerFileExplorer/PowerFileExplorer/src/main/java/com/amaze/filemanager/utils/color/ColorPreference.java
package com.amaze.filemanager.utils.color;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.drawable.ColorDrawable;
import android.support.annotation.ColorInt;
import android.support.annotation.ColorRes;
import android.util.Log;

import net.gnu.explorer.R;
import com.amaze.filemanager.utils.Utils;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * The ColorPreference class stores the user's preference for each {@link ColorUsage} and provides tools to:
 * - Access these colors as recource id, interer representation or String representation
 * - Load and save the preferences in a {@link SharedPreferences} object
 */
public class ColorPreference {
    public static final List<Integer> availableColors = Arrays.<Integer>asList(new Integer[]{
		Integer.valueOf(R.color.primary_red),
		Integer.valueOf(R.color.primary_pink),
		Integer.valueOf(R.color.primary_purple),
		Integer.valueOf(R.color.primary_deep_purple),
		Integer.valueOf(R.color.primary_indigo),
		Integer.valueOf(R.color.primary_blue),
		Integer.valueOf(R.color.primary_light_blue),
		Integer.valueOf(R.color.primary_cyan),
		Integer.valueOf(R.color.primary_teal),
		Integer.valueOf(R.color.primary_green),
		Integer.valueOf(R.color.primary_light_green),
		Integer.valueOf(R.color.primary_amber),
		Integer.valueOf(R.color.primary_orange),
		Integer.valueOf(R.color.primary_deep_orange),
		Integer.valueOf(R.color.primary_brown),
		Integer.valueOf(R.color.primary_grey_900),
		Integer.valueOf(R.color.primary_blue_grey),
		Integer.valueOf(R.color.primary_teal_900)}
    );
	
    private Map<ColorUsage, Integer> colors;
    private Context context;

    private ColorPreference(Context context) {
        this.context = context;
        this.colors = new HashMap<>();
    }

    /**
     * Compatibility code for use with legacy. Returns the index of the ColorResource given in the availableColors array.
     * Used for storing the color prefererences in the {@link SharedPreferences} object.
     *
     * @param colorResource The resouce
     * @return Its index in the availableColors array.
     */
    @Deprecated
    private static int colorIndex(@ColorRes int colorResource) {
        return availableColors.indexOf(colorResource);
    }

    /**
     * Compatibility code for use zith legacy. Retrieves a ColorResource given its index in the availableColors array.
     * Used to load color preferences from the {@link SharedPreferences} object.
     *
     * @param colorIndex An index
     * @return The color with the given index.
     */
    @Deprecated
    @ColorRes
    private static int getColorByIndex(int colorIndex) {
        return availableColors.get(colorIndex).intValue();
    }

    public static ColorPreference loadFromPreferences(Context context, SharedPreferences preferences) {
        ColorPreference cp = new ColorPreference(context);
        boolean prefCorrupted = false;

        for (ColorUsage usage : ColorUsage.values()) {
            try {
                int val = preferences.getInt(usage.asString(), colorIndex(usage.getDefaultColor()));
                cp.setRes(usage, getColorByIndex(val));
            } catch (ClassCastException ex) {
                Log.d("ColorPreference", "Got a ClassCastException while retrieving preference " + usage.asString());
                cp.setRes(usage, usage.getDefaultColor());
                prefCorrupted = true;
            }
        }

        if (prefCorrupted) {
            cp.saveToPreferences(preferences);
        }

        return cp;
    }

    /**
     * Combinations used when randimizing color selection at startup.
     */
    private static int[][] combinations = new int[][]{
            {14, 11, 12},
            {4, 1, 4},
            {8, 12, 8},
            {17, 11, 12},
            {3, 1, 3},
            {16, 14, 16},
            {1, 12, 1},
            {16, 0, 16},
            {0, 12, 0},
            {6, 1, 6},
            {7, 1, 7}
    };

    /**
     * Randomizes (but does not save) the colors used by the interface.
     *
     * @return The {@link ColorPreference} object itself.
     */
    public ColorPreference randomize() {
        int[] colorPos = combinations[new Random().nextInt(combinations.length - 1)];
        setRes(ColorUsage.PRIMARY, getColorByIndex(colorPos[0]));
        setRes(ColorUsage.PRIMARY_TWO, getColorByIndex(colorPos[0]));
        setRes(ColorUsage.ACCENT, getColorByIndex(colorPos[1]));
        setRes(ColorUsage.ICON_SKIN, getColorByIndex(colorPos[2]));

        return this;
    }

    /**
     * Saves the colors preferences in the {@link SharedPreferences} object given.
     *
     * @param preferences The {@link SharedPreferences} object in which the preferences are stored
     * @return The {@link ColorPreference} object itself.
     */
    public ColorPreference saveToPreferences(SharedPreferences preferences) {
        SharedPreferences.Editor e = preferences.edit();
        for (ColorUsage usage : colors.keySet()) {
            e.putInt(usage.asString(), colorIndex(getRes(usage)));
        }

        e.apply();

        Log.d("ColorPreference", "ColorPreference saved to SharedPreferences successfully.");

        return this;
    }

    /**
     * Sets the color resource for the given {@link ColorUsage}
     *
     * @param usage The {@link ColorUsage}
     * @param color The new color
     * @return The {@link ColorPreference} instance itself.
     */
    public ColorPreference setRes(ColorUsage usage, @ColorRes int color) {
        colors.put(usage, color);

        return this;
    }

    /**
     * Get the color resource preference for the given {@link ColorUsage}
     *
     * @param usage The {@link ColorUsage}
     * @return The color resource id.
     */
    @ColorRes
    private int getRes(ColorUsage usage) {
        @ColorRes Integer color = colors.get(usage);

        return color == null ? usage.getDefaultColor() : color.intValue();
    }

    /**
     * Get the color preference for the given {@link ColorUsage}
     *
     * @param usage The {@link ColorUsage}
     * @return The color int.
     */
    @ColorInt
    public int getColor(ColorUsage usage) {
        try {
            return Utils.getColor(context, getRes(usage));
        } catch (Resources.NotFoundException ex) {
            Log.e("ColorPreference", "Color resource not found for " + usage.asString() + ": " + Integer.toString(getRes(usage)));
            return Utils.getColor(context, usage.getDefaultColor());
        }
    }

    /**
     * Shortcut to get a {@link ColorDrawable} of the color preference associated with the given {@link ColorUsage}
     *
     * @param usage The {@link ColorUsage}
     * @return The {@link ColorDrawable}
     */
    public ColorDrawable getDrawable(ColorUsage usage) {
        return new ColorDrawable(getColor(usage));
    }

    /**
     * Get the color representation assiciated with the {@link ColorUsage} as a 6-digit Hexadecimal String
     *
     * @param usage The {@link ColorUsage}
     * @return The hex String
     */
    @Deprecated
    public String getColorAsString(ColorUsage usage) {
        return String.format("#%06X", (0xFFFFFF & getColor(usage)));
    }

}
