/**
   * Creates a new Backup
   *
   * @param useExternalStorage use external storage path instead of internal?
   * @param name name of backup
   * @param force overwrite existing folders?
   * @throws CreateBackupException
   * @throws BackupAlreadyExistsException
   */
  public void createBackup(boolean useExternalStorage, @NonNull String name, boolean force)
      throws CreateBackupException, BackupAlreadyExistsException {
    if (useExternalStorage) {
      // TODO: kp wie man internen und externen speicher unterscheidet
    } else {
      File src;
      File dst;

      dst = new File(SmartphonePreferencesHandler.getBackupPath() + File.separator + name);
      if (!dst.exists()) {
        dst.mkdirs();
      } else {
        if (force) {
          // remove existing backup
          try {
            if (!deleteRecursive(dst)) {
              throw new CreateBackupException("Error deleting existing Backup");
            }
          } catch (Exception e) {
            Log.e(e);
            throw new CreateBackupException(e);
          }
          dst.mkdirs();
        } else {
          throw new BackupAlreadyExistsException();
        }
      }

      try {
        // copy database
        src = new File(context.getFilesDir().getParent() + File.separator + "databases");
        dst =
            new File(
                SmartphonePreferencesHandler.getBackupPath()
                    + File.separator
                    + name
                    + File.separator
                    + "databases");
        if (src.exists()) {
          copyDirectory(src, dst);
        }

        // copy preferences
        src = new File(context.getFilesDir().getParent() + File.separator + "shared_prefs");
        dst =
            new File(
                SmartphonePreferencesHandler.getBackupPath()
                    + File.separator
                    + name
                    + File.separator
                    + "shared_prefs");
        if (src.exists()) {
          copyDirectory(src, dst);
        }
      } catch (Exception e) {
        Log.e(e);
        throw new CreateBackupException(e);
      }
    }
  }
  /**
   * Rename existing Backup
   *
   * @param oldName old backup name
   * @param newName new backup name
   * @throws BackupNotFoundException
   * @throws BackupAlreadyExistsException
   */
  public void renameBackup(@NonNull String oldName, @NonNull String newName)
      throws BackupNotFoundException, BackupAlreadyExistsException {
    File oldFolder =
        new File(SmartphonePreferencesHandler.getBackupPath() + File.separator + oldName);
    File newFolder =
        new File(SmartphonePreferencesHandler.getBackupPath() + File.separator + newName);

    if (!oldFolder.exists()) {
      throw new BackupNotFoundException();
    }
    if (newFolder.exists()) {
      throw new BackupAlreadyExistsException();
    }
    oldFolder.renameTo(newFolder);
  }
  /**
   * Get all Backups
   *
   * @return List of Backups
   */
  @NonNull
  public ArrayList<Backup> getBackups() {
    ArrayList<Backup> backups = new ArrayList<>();
    File backupDir = new File(SmartphonePreferencesHandler.getBackupPath());

    FileFilter backupFileFilter =
        new FileFilter() {
          @Override
          public boolean accept(File pathname) {
            if (pathname.list() == null) {
              return false;
            }

            List<String> subFolders = Arrays.asList(pathname.list());
            return pathname.isDirectory()
                && subFolders.contains("shared_prefs")
                && subFolders.contains("databases");
          }
        };

    if (backupDir.exists()) {
      for (File file : backupDir.listFiles(backupFileFilter)) {
        backups.add(
            new Backup(
                file.getName(),
                new Date(file.lastModified()),
                backupDir + File.separator + file.getName(),
                false));
      }
    }
    return backups;
  }
  /**
   * Restore Backup
   *
   * @param name name of backup
   * @throws BackupNotFoundException
   * @throws RestoreBackupException
   */
  public void restoreBackup(@NonNull String name)
      throws BackupNotFoundException, RestoreBackupException {
    // create source path object
    File src = new File(SmartphonePreferencesHandler.getBackupPath() + File.separator + name);
    if (src.exists()) {
      try {
        // create destination path object
        File dst = new File(context.getFilesDir().getParent());

        // delete existing files
        for (File fileOrFolder : dst.listFiles()) {
          if (fileOrFolder
                  .getPath()
                  .equals(context.getFilesDir().getParent() + File.separator + "shared_prefs")
              || fileOrFolder
                  .getPath()
                  .equals(context.getFilesDir().getParent() + File.separator + "databases")) {
            deleteRecursive(fileOrFolder);
          }
        }
        // copy directory to system folder
        copyDirectory(src, dst);
      } catch (Exception e) {
        Log.e(e);
        throw new RestoreBackupException(e);
      }
    } else {
      throw new BackupNotFoundException();
    }
  }
 /**
  * Remove a Backup
  *
  * @param name name of backup
  * @throws BackupNotFoundException
  * @throws RemoveBackupException
  */
 public void removeBackup(@NonNull String name)
     throws BackupNotFoundException, RemoveBackupException {
   try {
     File backupFolder =
         new File(SmartphonePreferencesHandler.getBackupPath() + File.separator + name);
     if (!backupFolder.exists()) {
       throw new BackupNotFoundException();
     }
     deleteRecursive(backupFolder);
   } catch (Exception e) {
     Log.e(e);
     throw new RemoveBackupException(e);
   }
 }