package com.marverenic.music.data.store;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ActivityManager.TaskDescription;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.SystemClock;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
import android.support.annotation.StyleRes;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.res.ResourcesCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.AppCompatDelegate;
import android.support.v7.app.NightMode;
import com.marverenic.music.R;
import com.marverenic.music.activity.MainActivity;
import com.marverenic.music.data.annotations.AccentTheme;
import com.marverenic.music.data.annotations.PrimaryTheme;
import com.marverenic.music.player.PlayerService;
import static android.util.DisplayMetrics.DENSITY_HIGH;
import static android.util.DisplayMetrics.DENSITY_LOW;
import static android.util.DisplayMetrics.DENSITY_MEDIUM;
import static android.util.DisplayMetrics.DENSITY_XHIGH;
import static android.util.DisplayMetrics.DENSITY_XXHIGH;
import static android.util.DisplayMetrics.DENSITY_XXXHIGH;
import static com.marverenic.music.data.annotations.BaseTheme.AUTO;
import static com.marverenic.music.data.annotations.BaseTheme.DARK;
import static com.marverenic.music.data.annotations.BaseTheme.LIGHT;
public class PresetThemeStore implements ThemeStore {
private Context mContext;
private PreferenceStore mPreferenceStore;
public PresetThemeStore(Context context, PreferenceStore preferenceStore) {
mContext = context;
mPreferenceStore = preferenceStore;
}
@Override
public int getPrimaryColor() {
return ContextCompat.getColor(mContext, getPrimaryColorRes());
}
@ColorRes
private int getPrimaryColorRes() {
switch (mPreferenceStore.getPrimaryColor()) {
case PrimaryTheme.GRAY:
return R.color.primary_grey;
case PrimaryTheme.RED:
return R.color.primary_red;
case PrimaryTheme.ORANGE:
return R.color.primary_orange;
case PrimaryTheme.YELLOW:
return R.color.primary_yellow;
case PrimaryTheme.GREEN:
return R.color.primary_green;
case PrimaryTheme.CYAN:
return R.color.primary;
case PrimaryTheme.BLUE:
return R.color.primary_blue;
case PrimaryTheme.PURPLE:
return R.color.primary_purple;
case PrimaryTheme.BLACK:
return R.color.primary_black;
default:
return R.color.primary;
}
}
@Override
public int getAccentColor() {
return ContextCompat.getColor(mContext, getAccentColorRes());
}
@ColorRes
private int getAccentColorRes() {
switch (mPreferenceStore.getAccentColor()) {
case AccentTheme.GRAY:
return R.color.accent_grey;
case AccentTheme.RED:
return R.color.accent_red;
case AccentTheme.ORANGE:
return R.color.accent_orange;
case AccentTheme.YELLOW:
return R.color.accent_yellow;
case AccentTheme.GREEN:
return R.color.accent_green;
case AccentTheme.CYAN:
return R.color.accent;
case AccentTheme.BLUE:
return R.color.accent_blue;
case AccentTheme.PURPLE:
return R.color.accent_purple;
case AccentTheme.TEAL:
return R.color.accent_black;
default:
return R.color.accent;
}
}
@Override
public void setTheme(AppCompatActivity activity) {
applyNightMode(activity);
activity.setTheme(R.style.AppTheme);
activity.getTheme().applyStyle(getPrimaryThemeId(), true);
activity.getTheme().applyStyle(getAccentThemeId(), true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
applyTaskDescription(activity);
}
}
private void applyNightMode(AppCompatActivity activity) {
AppCompatDelegate.setDefaultNightMode(getNightMode());
activity.getDelegate().applyDayNight();
}
@NightMode
private int getNightMode() {
switch (mPreferenceStore.getBaseColor()) {
case AUTO:
return AppCompatDelegate.MODE_NIGHT_AUTO;
case DARK:
return AppCompatDelegate.MODE_NIGHT_YES;
case LIGHT:
default:
return AppCompatDelegate.MODE_NIGHT_NO;
}
}
@StyleRes
private int getPrimaryThemeId() {
switch (mPreferenceStore.getPrimaryColor()) {
case PrimaryTheme.GRAY:
return R.style.Primary_Grey;
case PrimaryTheme.RED:
return R.style.Primary_Red;
case PrimaryTheme.ORANGE:
return R.style.Primary_Orange;
case PrimaryTheme.YELLOW:
return R.style.Primary_Yellow;
case PrimaryTheme.GREEN:
return R.style.Primary_Green;
case PrimaryTheme.CYAN:
return R.style.Primary_Cyan;
case PrimaryTheme.BLUE:
return R.style.Primary_Blue;
case PrimaryTheme.PURPLE:
return R.style.Primary_Purple;
case PrimaryTheme.BLACK:
return R.style.Primary_Black;
default:
return R.style.Primary_Cyan;
}
}
@StyleRes
private int getAccentThemeId() {
switch (mPreferenceStore.getAccentColor()) {
case AccentTheme.GRAY:
return R.style.Accent_Grey;
case AccentTheme.RED:
return R.style.Accent_Red;
case AccentTheme.ORANGE:
return R.style.Accent_Orange;
case AccentTheme.YELLOW:
return R.style.Accent_Yellow;
case AccentTheme.GREEN:
return R.style.Accent_Green;
case AccentTheme.CYAN:
return R.style.Accent_Cyan;
case AccentTheme.BLUE:
return R.style.Accent_Blue;
case AccentTheme.PURPLE:
return R.style.Accent_Purple;
case AccentTheme.TEAL:
return R.style.Accent_Black;
default:
return R.style.Accent_Cyan;
}
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void applyTaskDescription(Activity activity) {
String taskName = mContext.getString(R.string.app_name);
int taskColor = getPrimaryColor();
Bitmap taskIcon = getAppIcon();
TaskDescription taskDescription = new TaskDescription(taskName, taskIcon, taskColor);
activity.setTaskDescription(taskDescription);
}
private Bitmap getAppIcon() {
return BitmapFactory.decodeResource(mContext.getResources(), getIconId());
}
@Override
public Bitmap getLargeAppIcon() {
Drawable icon = ResourcesCompat.getDrawableForDensity(mContext.getResources(), getIconId(),
getLargerDisplayDensity(), mContext.getTheme());
if (icon instanceof BitmapDrawable) {
return ((BitmapDrawable) icon).getBitmap();
} else {
return null;
}
}
private int getLargerDisplayDensity() {
int screenDensity = mContext.getResources().getDisplayMetrics().densityDpi;
if (screenDensity == DENSITY_LOW) {
return DENSITY_MEDIUM;
} else if (screenDensity == DENSITY_MEDIUM) {
return DENSITY_HIGH;
} else if (screenDensity == DENSITY_HIGH) {
return DENSITY_XHIGH;
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
return DENSITY_XHIGH;
} else if (screenDensity == DENSITY_XHIGH) {
return DENSITY_XXHIGH;
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
return DENSITY_XXHIGH;
} else {
return DENSITY_XXXHIGH;
}
}
@DrawableRes
private int getIconId() {
switch (mPreferenceStore.getPrimaryColor()) {
case PrimaryTheme.GRAY:
return R.mipmap.ic_launcher_grey;
case PrimaryTheme.RED:
return R.mipmap.ic_launcher_red;
case PrimaryTheme.ORANGE:
return R.mipmap.ic_launcher_orange;
case PrimaryTheme.YELLOW:
return R.mipmap.ic_launcher_yellow;
case PrimaryTheme.GREEN:
return R.mipmap.ic_launcher_green;
case PrimaryTheme.CYAN:
return R.mipmap.ic_launcher;
case PrimaryTheme.BLUE:
return R.mipmap.ic_launcher_blue;
case PrimaryTheme.PURPLE:
return R.mipmap.ic_launcher_purple;
case PrimaryTheme.BLACK:
return R.mipmap.ic_launcher_black;
default:
return R.mipmap.ic_launcher;
}
}
@Override
public void createThemedLauncherIcon() {
String[] activityThemeSuffixes = {
"$Grey",
"$Red",
"$Orange",
"$Yellow",
"$Green",
"", // The cyan theme does not have an Activity name suffix
"$Purple",
"$Black",
"$Blue"
};
String launchActivityName = "com.marverenic.music.activity.LibraryActivity";
int nextIcon = mPreferenceStore.getPrimaryColor();
int currIcon = mPreferenceStore.getIconColor();
if (nextIcon == currIcon) {
return;
}
mPreferenceStore.setIconColor(nextIcon);
mPreferenceStore.commit();
restartApplication();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
// On Nougat and newer versions of Android, PackageManager will automatically restart
// Jockey. On older versions, it will just kill Jockey after disabling the current
// launcher component. Therefore, we schedule an alarm 100 ms in the future to restart
// Jockey.
scheduleRestart();
}
setComponentEnabled(launchActivityName + activityThemeSuffixes[nextIcon], true);
setComponentEnabled(launchActivityName + activityThemeSuffixes[currIcon], false);
}
private void scheduleRestart() {
PendingIntent intent = PendingIntent.getActivity(mContext, 0,
new Intent(mContext, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager mgr = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
long restartTime = SystemClock.elapsedRealtime() + 100;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
mgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, restartTime, intent);
} else {
mgr.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, restartTime, intent);
}
}
private void restartApplication() {
mContext.stopService(new Intent(mContext, PlayerService.class));
Intent restartIntent = new Intent(mContext, MainActivity.class);
restartIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(restartIntent);
}
private void setComponentEnabled(String fullyQualifiedName, boolean enabled) {
mContext.getPackageManager().setComponentEnabledSetting(
new ComponentName(mContext.getPackageName(), fullyQualifiedName),
(enabled)
? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
: PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
(enabled) ? PackageManager.DONT_KILL_APP : 0);
}
}