content: package me.anon.grow;
  
  import android.app.AlarmManager;
  import android.app.PendingIntent;
  import android.content.Context;
  import android.content.Intent;
  import android.content.SharedPreferences;
  import android.graphics.Bitmap;
  import android.os.Build;
  import android.os.Environment;
  import android.preference.PreferenceManager;
  import android.text.TextUtils;
  
  import com.nostra13.universalimageloader.cache.disc.DiskCache;
  import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache;
  import com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator;
  import com.nostra13.universalimageloader.core.DefaultConfigurationFactory;
  import com.nostra13.universalimageloader.core.DisplayImageOptions;
  import com.nostra13.universalimageloader.core.ImageLoader;
  import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
  import com.nostra13.universalimageloader.core.decode.BaseImageDecoder;
  import com.nostra13.universalimageloader.core.decode.ImageDecodingInfo;
  import com.nostra13.universalimageloader.utils.IoUtils;
  import com.nostra13.universalimageloader.utils.StorageUtils;
  
  import java.io.BufferedOutputStream;
  import java.io.File;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.net.URI;
  import java.net.URISyntaxException;
  import java.util.concurrent.TimeUnit;
  import java.util.concurrent.atomic.AtomicBoolean;
  
  import androidx.multidex.MultiDexApplication;
  import me.anon.controller.receiver.BackupService;
  import me.anon.lib.handler.ExceptionHandler;
  import me.anon.lib.helper.BackupHelper;
  import me.anon.lib.manager.FileManager;
  import me.anon.lib.manager.GardenManager;
  import me.anon.lib.manager.PlantManager;
  import me.anon.lib.manager.ScheduleManager;
  import me.anon.lib.stream.DecryptInputStream;
  import me.anon.lib.stream.EncryptOutputStream;
  
  public class MainApplication extends MultiDexApplication
  {
  	private static DisplayImageOptions displayImageOptions;
  	private static boolean encrypted = false;
  	private static String key = "";
  	private static boolean failsafe = false;
  	private static boolean isTablet = false;
  	public static boolean isPanic = false;
  
  	public static void setEncrypted(boolean encrypted)
  	{
  		MainApplication.encrypted = encrypted;
  	}
  
  	public static void setKey(String key)
  	{
  		MainApplication.key = key;
  	}
  
  	public static void setFailsafe(boolean failsafe)
  	{
  		MainApplication.failsafe = failsafe;
  	}
  
  	public static void setIsTablet(boolean isTablet)
  	{
  		MainApplication.isTablet = isTablet;
  	}
  
  	public static DisplayImageOptions getDisplayImageOptions()
  	{
  		return displayImageOptions;
  	}
  
  	public static boolean isEncrypted()
  	{
  		return encrypted;
  	}
  
  	public static String getKey()
  	{
  		return key;
  	}
  
  	public static boolean isFailsafe()
  	{
  		return failsafe;
  	}
  
  	public static boolean isTablet()
  	{
  		return isTablet;
  	}
  
  	public static AtomicBoolean dataTaskRunning = new AtomicBoolean(false);
  	private static Context context;
  	public static SharedPreferences getDefaultPreferences()
  	{
  		return PreferenceManager.getDefaultSharedPreferences(context);
  	}
  
  	@Override public void onCreate()
  	{
  		super.onCreate();
  
  		context = this;
  		ExceptionHandler.getInstance().register(this);
  
  		PlantManager.getInstance().initialise(this);
  		encrypted = PreferenceManager.getDefaultSharedPreferences(this).getBoolean("encrypt", false) || PlantManager.isFileEncrypted();
  
  		BackupHelper.FILES_PATH = PreferenceManager.getDefaultSharedPreferences(this).getString("backup_location", "");
  		FileManager.IMAGE_PATH = PreferenceManager.getDefaultSharedPreferences(this).getString("image_location", "");
  		if (TextUtils.isEmpty(BackupHelper.FILES_PATH)) BackupHelper.FILES_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + "/backups/GrowTracker/";
  		if (TextUtils.isEmpty(FileManager.IMAGE_PATH)) FileManager.IMAGE_PATH = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getPath() + "/GrowTracker/";
  		new File(FileManager.IMAGE_PATH).mkdirs();
  		new File(BackupHelper.FILES_PATH).mkdirs();
  
  		isTablet = getResources().getBoolean(R.bool.is_tablet);
  
  		PlantManager.getInstance().load();
  		GardenManager.getInstance().initialise(this);
  		ScheduleManager.instance.initialise(this);
  		registerBackupService();
  
  		displayImageOptions = new DisplayImageOptions.Builder()
  			//.cacheInMemory(true)
  			.cacheOnDisk(true)
  			.showImageOnLoading(R.drawable.ic_image)
  			.showImageOnFail(R.drawable.default_plant)
  			.bitmapConfig(Bitmap.Config.RGB_565)
  			.considerExifParams(true)
  			.build();
  
  		final FileNameGenerator fileNameGenerator = DefaultConfigurationFactory.createFileNameGenerator();
  		final DiskCache diskCache = new UnlimitedDiskCache(StorageUtils.getCacheDirectory(context), getExternalCacheDir(), fileNameGenerator);
  		((UnlimitedDiskCache)diskCache).setCompressFormat(Bitmap.CompressFormat.JPEG);
  		((UnlimitedDiskCache)diskCache).setCompressQuality(85);
  		ImageLoader.getInstance().init(new ImageLoaderConfiguration.Builder(this)
  			.threadPoolSize(6)
  			.diskCache(new DiskCache()
  			{
  				@Override public File getDirectory()
  				{
  					return diskCache.getDirectory();
  				}
  
  				@Override public File get(String imageUri)
  				{
  					if (isEncrypted()) return null;
  					else return diskCache.get(imageUri);
  				}
  
  				@Override public boolean save(String imageUri, InputStream imageStream, IoUtils.CopyListener listener) throws IOException
  				{
  					if (encrypted)
  					{
  						File imageFile = getFile(imageUri);
  						File tmpFile = new File(imageFile.getAbsolutePath() + ".tmp");
  						boolean loaded = imageFile.exists();
  
  						if (!loaded)
  						{
  							try
  							{
  								OutputStream os = new BufferedOutputStream(new EncryptOutputStream(key, tmpFile), 32 * 1024);
  								try
  								{
  									loaded = IoUtils.copyStream(imageStream, os, listener, 32 * 1024);
  								}
  								finally
  								{
  									IoUtils.closeSilently(os);
  								}
  							}
  							finally
  							{
  								if (loaded && !tmpFile.renameTo(imageFile))
  								{
  									loaded = false;
  								}
  								if (!loaded)
  								{
  									tmpFile.delete();
  								}
  							}
  						}
  
  						return loaded;
  					}
  					else
  					{
  						return diskCache.save(imageUri, imageStream, listener);
  					}
  				}
  
  				@Override public boolean save(String imageUri, Bitmap bitmap) throws IOException
  				{
  					if (encrypted)
  					{
  						File imageFile = getFile(imageUri);
  						File tmpFile = new File(imageFile.getAbsolutePath() + ".tmp");
  						OutputStream os = new BufferedOutputStream(new EncryptOutputStream(key, tmpFile), 32 * 1024);
  						boolean savedSuccessfully = false;
  						try
  						{
  							savedSuccessfully = bitmap.compress(Bitmap.CompressFormat.JPEG, 85, os);
  						}
  						finally
  						{
  							IoUtils.closeSilently(os);
  							if (savedSuccessfully && !tmpFile.renameTo(imageFile))
  							{
  								savedSuccessfully = false;
  							}
  							if (!savedSuccessfully)
  							{
  								tmpFile.delete();
  							}
  						}
  
  						bitmap.recycle();
  						return savedSuccessfully;
  					}
  					else
  					{
  						return diskCache.save(imageUri, bitmap);
  					}
  				}
  
  				@Override public boolean remove(String imageUri)
  				{
  					return diskCache.remove(imageUri);
  				}
  
  				@Override public void close()
  				{
  					diskCache.close();
  				}
  
  				@Override public void clear()
  				{
  					diskCache.clear();
  				}
  
  				/**
  				 * Returns file object (not null) for incoming image URI. File object can reference to non-existing file.
  				 */
  				protected File getFile(String imageUri)
  				{
  					String fileName = fileNameGenerator.generate(imageUri);
  					File dir = StorageUtils.getCacheDirectory(context);
  					File dir2 = StorageUtils.getIndividualCacheDirectory(context);
  					if (!dir.exists() && !dir.mkdirs())
  					{
  						if (dir2 != null && (dir2.exists() || dir2.mkdirs()))
  						{
  							dir = dir2;
  						}
  					}
  
  					return new File(dir, fileName);
  				}
  			})
  			.diskCacheExtraOptions(768, 768, null)
  			.imageDecoder(new BaseImageDecoder(false)
  			{
  				@Override protected InputStream getImageStream(ImageDecodingInfo decodingInfo) throws IOException
  				{
  					if (encrypted)
  					{
  						try
  						{
  							return new DecryptInputStream(key, new File(new URI(decodingInfo.getOriginalImageUri())));
  						}
  						catch (URISyntaxException e)
  						{
  							e.printStackTrace();
  						}
  					}
  
  					return super.getImageStream(decodingInfo);
  				}
  			})
  			.build());
  	}
  
  	public void registerBackupService()
  	{
  		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
  
  		if (prefs.getBoolean("auto_backup", false))
  		{
  			Intent backupIntent = new Intent(this, BackupService.class);
  
  			AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
  			alarmManager.cancel(PendingIntent.getBroadcast(this, 0, backupIntent, (Build.VERSION.SDK_INT >= 31 ? PendingIntent.FLAG_MUTABLE : 0)));
  			alarmManager.setRepeating(AlarmManager.RTC, System.currentTimeMillis(), TimeUnit.DAYS.toMillis(1), PendingIntent.getBroadcast(this, 0, backupIntent, (Build.VERSION.SDK_INT >= 31 ? PendingIntent.FLAG_MUTABLE : 0)));
  		}
  	}
  }
  