/** Method to read the properties and adding them to the pane */
  private void readProperties() {
    ProfileProperties profile = PropertiesUtils.getProfile();

    // Musiclibrary properties
    musicLibraryPath.setText(profile.getPathToMusicLibrary());
    OrderingProperty orderIngProperty = profile.getOrderingMode();

    if (orderIngProperty == OrderingProperty.GAA) {
      orderingMode.setValue(GAA);
    } else if (orderIngProperty == OrderingProperty.AA) {
      orderingMode.setValue(AA);
    } else {
      orderingMode.setValue(AAA);
    }

    if (profile.getPlayListHeader().contains("german")) {
      playListHeaderMode.setValue(germanHeader);
    } else {
      playListHeaderMode.setValue(englishHeader);
    }

    // Import properties
    keepFiles.setSelected(profile.isKeepOriginalFiles());
    justTagFiles.setSelected(profile.isJustTagFiles());

    // Playlist properties
    playListExport.setSelected(profile.isPlayListExport());
    playListExportPath.setText(profile.getPlayListExportDir());
  }
  /**
   * Method to generate the new file path
   *
   * @throws IOException Gets thrown if the directory can't be made
   */
  public static void generateNewFilePath(MusicFile file) throws IOException {
    MusicTag tag = file.getTag();
    OrderingProperty orderingProperty = PropertiesUtils.getOrderingProperty();

    if (!tag.getArtist().equals("") && !tag.getAlbum().equals("")) {
      if (orderingProperty == OrderingProperty.GAA && !tag.getGenre().equals("")
          || orderingProperty == OrderingProperty.AA
          || orderingProperty == OrderingProperty.AAA) {
        file.setNewFilePathIsSet(true);
        file.setNewFilePath(MusicFileUtils.makeFileDir(file));
      } else {
        file.setNewFilePathIsSet(false);
        file.setNewFilePath("");
      }
    } else {
      file.setNewFilePathIsSet(false);
      file.setNewFilePath("");
    }
  }
  /** Constructs the profile grid pane */
  private ProfileSettings() {
    // Setting the style sheet
    this.getStylesheets()
        .add(this.getClass().getResource("css/profile_settings.css").toExternalForm());
    this.getStyleClass().add("grid");

    // Library Settings
    musicLibrarySettings_Label = new Label("Music Library");
    musicLibrarySettings_Label.setId("LabelBig");

    musicLibraryPath_Label = new Label("Path to Library:");
    musicLibraryPath_Label.setId("LabelSmall");
    orderingMode_Label = new Label("Ordering Mode:");
    musicLibraryPath = new TextField("");
    musicLibraryPath.setEditable(false);

    orderingMode_Label = new Label("Ordering Mode");
    orderingMode_Label.setId("LabelSmall");
    orderingMode = new ChoiceBox<String>();
    orderingMode.setItems(FXCollections.observableArrayList(AAA, AA, GAA));

    chooseDirToMusicLibrary = new Button();
    chooseDirToMusicLibrary.setId("OpenFolderButton");
    chooseDirToMusicLibrary.setGraphic(
        new ImageView(PropertiesUtils.getProperty(IconProperties.OPEN_FOLDER_IMPORT)));
    chooseDirToMusicLibrary.setOnAction(getButtonSetLibraryEventHandler());

    CenterGridPane.setConstraints(musicLibrarySettings_Label, 0, 0, 3, 1);
    CenterGridPane.setConstraints(musicLibraryPath_Label, 0, 1, 1, 1);
    CenterGridPane.setConstraints(musicLibraryPath, 1, 1, 1, 1);
    CenterGridPane.setConstraints(chooseDirToMusicLibrary, 2, 1, 1, 1);
    CenterGridPane.setConstraints(orderingMode_Label, 0, 2, 1, 1);
    CenterGridPane.setConstraints(orderingMode, 1, 2, 3, 1);

    // Import Settings
    importSettings_Label = new Label("Import Settings");
    importSettings_Label.setId("LabelBig");
    keepFiles_Label = new Label("Keep original files:");
    keepFiles_Label.setId("LabelSmall");
    keepFiles = new RadioButton();

    justTagFiles_Label = new Label("Just tag files:");
    justTagFiles_Label.setId("LabelSmall");
    justTagFiles = new RadioButton();

    CenterGridPane.setConstraints(importSettings_Label, 0, 4, 3, 1);
    CenterGridPane.setConstraints(keepFiles_Label, 0, 5, 1, 1);
    CenterGridPane.setConstraints(keepFiles, 1, 5, 1, 1);
    CenterGridPane.setConstraints(justTagFiles_Label, 0, 6, 1, 1);
    CenterGridPane.setConstraints(justTagFiles, 1, 6, 1, 1);

    // Playlist export settings
    playlistSettings_Label = new Label("Playlist Export Settings");
    playlistSettings_Label.setId("LabelBig");

    playListExport_Label = new Label("Playlist Export");
    playListExport_Label.setId("LabelSmall");
    playListExport = new RadioButton();

    playListName_Label = new Label("Playlist-Name:");
    playListName_Label.setId("LabelSmall");
    playListName = new TextField();

    playListExportPath_Label = new Label("Export Directory");
    playListExportPath_Label.setId("LabelSmall");
    playListExportPath = new TextField("");
    playListExportPath.setEditable(false);
    chooseDirToExportPlayList = new Button();
    chooseDirToExportPlayList.setId("OpenFolderButton");
    chooseDirToExportPlayList.setGraphic(
        new ImageView(PropertiesUtils.getProperty(IconProperties.OPEN_FOLDER_IMPORT)));
    chooseDirToExportPlayList.setOnAction(getButtonSetPlayListDirEventHandler());
    playListHeader = new Label("Playlist Header-Language");
    playListHeaderMode = new ChoiceBox<String>();
    playListHeaderMode.setItems(FXCollections.observableArrayList(germanHeader, englishHeader));

    CenterGridPane.setConstraints(playlistSettings_Label, 0, 8, 3, 1);
    CenterGridPane.setConstraints(playListExport_Label, 0, 9, 1, 1);
    CenterGridPane.setConstraints(playListExport, 1, 9, 1, 1);
    CenterGridPane.setConstraints(playListName_Label, 0, 10, 1, 1);
    CenterGridPane.setConstraints(playListName, 1, 10, 1, 1);
    CenterGridPane.setConstraints(playListExportPath_Label, 0, 11, 1, 1);
    CenterGridPane.setConstraints(playListExportPath, 1, 11, 1, 1);
    CenterGridPane.setConstraints(chooseDirToExportPlayList, 2, 11, 1, 1);
    CenterGridPane.setConstraints(playListHeader, 0, 12, 1, 1);
    CenterGridPane.setConstraints(playListHeaderMode, 1, 12, 1, 1);

    /** Restore and apply button */
    applyButton = new Button("Apply");
    applyButton.setOnAction(getButtonApplyEventHandler());

    restoreButton = new Button("Restore");
    restoreButton.setOnAction(getButtonRestoreEventHandler());

    CenterGridPane.setConstraints(restoreButton, 1, 13, 1, 1, HPos.RIGHT, VPos.CENTER);
    CenterGridPane.setConstraints(applyButton, 2, 13, 1, 1);

    this.getChildren()
        .addAll(
            musicLibrarySettings_Label,
            musicLibraryPath_Label,
            musicLibraryPath,
            chooseDirToMusicLibrary,
            orderingMode_Label,
            orderingMode,
            importSettings_Label,
            keepFiles_Label,
            keepFiles,
            justTagFiles_Label,
            justTagFiles,
            playlistSettings_Label,
            playListExport_Label,
            playListExport,
            playListName_Label,
            playListName,
            playListExportPath_Label,
            playListExportPath,
            chooseDirToExportPlayList,
            restoreButton,
            applyButton,
            playListHeader,
            playListHeaderMode);

    /** Reading the properties and adding them to the pane */
    readProperties();
  }
  /**
   * Method for making the directory for the imported file
   *
   * @param musicFile
   * @return path to the directory
   * @throws IOException
   */
  public static String makeFileDir(MusicFile musicFile) throws IOException {
    File level_1;
    File level_2;
    File level_3;

    String pathToMusicLibrary;

    pathToMusicLibrary = PropertiesUtils.getProperty(LibraryProperties.FILEPATH);
    OrderingProperty orderingMode = PropertiesUtils.getOrderingProperty();

    // Cleaning artist and album
    String artist = cleanString(musicFile.getTag().getArtist());
    String album = cleanString(musicFile.getTag().getAlbum());
    artist = clearForbiddenCharacters(artist);
    album = clearForbiddenCharacters(album);

    // Ordering: A - Artist - Album
    if (orderingMode == OrderingProperty.AAA) {
      if (NUMBERS.contains(artist.substring(0, 1))) {
        level_1 = new File(pathToMusicLibrary + "\\" + "123");
        level_2 = new File(pathToMusicLibrary + "\\" + "123" + "\\" + artist);
        level_3 = new File(pathToMusicLibrary + "\\" + "123" + "\\" + artist + "\\" + album);
      } else {
        level_1 = new File(pathToMusicLibrary + "\\" + artist.substring(0, 1).toUpperCase());
        level_2 =
            new File(
                pathToMusicLibrary
                    + "\\"
                    + artist.toUpperCase().substring(0, 1).toUpperCase()
                    + "\\"
                    + (artist.toUpperCase()).substring(0, 1).toUpperCase()
                    + artist.substring(1, artist.length()));
        level_3 =
            new File(
                pathToMusicLibrary
                    + "\\"
                    + artist.toUpperCase().substring(0, 1).toUpperCase()
                    + "\\"
                    + (artist.toUpperCase()).substring(0, 1).toUpperCase()
                    + artist.substring(1, artist.length())
                    + "\\"
                    + (album.toUpperCase()).substring(0, 1).toUpperCase()
                    + album.substring(1, album.length()));
      }

      if (level_1.exists() == false) {
        level_1.mkdir();
      }

      if (level_2.exists() == false) {
        level_2.mkdir();
      }

      if (level_3.exists() == false) {
        level_3.mkdir();
      }

      return level_3.getAbsolutePath();

      // Genre - Artist - Album
    } else if (orderingMode == OrderingProperty.GAA) {
      String genre = cleanString(musicFile.getTag().getGenre());
      genre = clearForbiddenCharacters(genre);

      level_1 =
          new File(
              pathToMusicLibrary
                  + "\\"
                  + genre.substring(0, 1).toUpperCase()
                  + genre.substring(1, genre.length()));
      level_2 =
          new File(
              pathToMusicLibrary
                  + "\\"
                  + genre.substring(0, 1).toUpperCase()
                  + genre.substring(1, genre.length())
                  + "\\"
                  + artist.substring(0, 1).toUpperCase()
                  + artist.substring(1, artist.length()));
      level_3 =
          new File(
              pathToMusicLibrary
                  + "\\"
                  + genre.substring(0, 1).toUpperCase()
                  + genre.substring(1, genre.length())
                  + "\\"
                  + artist.substring(0, 1).toUpperCase()
                  + artist.substring(1, artist.length())
                  + "\\"
                  + album.substring(0, 1).toUpperCase()
                  + album.substring(1, album.length()));

      if (level_1.exists() == false) {
        level_1.mkdir();
      }

      if (level_2.exists() == false) {
        level_2.mkdir();
      }

      if (level_3.exists() == false) {
        level_3.mkdir();
      }

      return level_3.getAbsolutePath();

      // Artist - Album
    } else if (orderingMode == OrderingProperty.AA) {
      level_1 =
          new File(
              pathToMusicLibrary
                  + "\\"
                  + artist.toUpperCase().charAt(0)
                  + artist.substring(1, artist.length()));
      level_2 =
          new File(
              pathToMusicLibrary
                  + "\\"
                  + artist.toUpperCase().charAt(0)
                  + artist.substring(1, artist.length())
                  + "\\"
                  + album.substring(0, 1).toUpperCase()
                  + album.substring(1, album.length()));

      if (level_1.exists() == false) {
        level_1.mkdir();
      }

      if (level_2.exists() == false) {
        level_2.mkdir();
      }

      return level_2.getAbsolutePath();
    }

    return "";
  }
  /**
   * Checks for a certain file if there is already a music file in the library
   *
   * @param musicFile to be checked
   * @return boolean indicating whether there is a duplicate already
   */
  public static boolean checkForDuplicates(MusicFile musicFile)
      throws CannotReadException, IOException, TagException, ReadOnlyFileException,
          InvalidAudioFrameException {
    // The Directories
    File firstLevelDir;
    File secondLevelDir;
    File thridLevelDir;

    // The direcotryPaths
    String firstLevelDir_path;
    String secondLevelDir_path;
    String thridLevelDir_path;

    // Clearing the readFiles list
    readFiles.clear();

    // Reading the tag
    MusicTag tag = musicFile.getTag();
    boolean duplicate = false;

    // Reading the path to the music library and ordering Mode
    String pathToLibrary = PropertiesUtils.getProperty(LibraryProperties.FILEPATH);
    OrderingProperty orderingMode = PropertiesUtils.getOrderingProperty();

    // Cleaning the Strings
    String artist =
        MusicFileUtils.clearForbiddenCharacters(MusicFileUtils.cleanString(tag.getArtist()));
    String album =
        MusicFileUtils.clearForbiddenCharacters(MusicFileUtils.cleanString(tag.getAlbum()));
    String titlename =
        MusicFileUtils.clearForbiddenCharacters(MusicFileUtils.cleanString(tag.getTitlename()));
    String genre =
        MusicFileUtils.clearForbiddenCharacters(MusicFileUtils.cleanString(tag.getGenre()));

    if (orderingMode == OrderingProperty.AAA || orderingMode == OrderingProperty.GAA) {
      // Building the Directorystrings
      // Ordering: A - Artist - Album
      if (orderingMode == OrderingProperty.AAA) {
        firstLevelDir_path = pathToLibrary + "\\" + artist.substring(0, 1).toUpperCase();
        secondLevelDir_path =
            firstLevelDir_path
                + "\\"
                + artist.substring(0, 1).toUpperCase()
                + artist.substring(1, artist.length());
        thridLevelDir_path =
            secondLevelDir_path
                + "\\"
                + album.substring(0, 1).toUpperCase()
                + album.substring(1, album.length());
        // Genre - Artist - Album
      } else {
        firstLevelDir_path =
            pathToLibrary
                + "\\"
                + genre.substring(0, 1).toUpperCase()
                + genre.substring(1, genre.length()).toUpperCase();
        secondLevelDir_path =
            firstLevelDir_path
                + "\\"
                + artist.substring(0, 1).toUpperCase()
                + artist.substring(1, artist.length());
        thridLevelDir_path =
            secondLevelDir_path
                + "\\"
                + album.substring(0, 1).toUpperCase()
                + album.substring(1, album.length());
      }

      // First checking whether there is a Directory for the music file
      firstLevelDir = new File(firstLevelDir_path);
      secondLevelDir = new File(secondLevelDir_path);
      thridLevelDir = new File(thridLevelDir_path);

      // The artist subFolder exists
      if (firstLevelDir.exists()) {
        if (secondLevelDir.exists()) {
          if (thridLevelDir.exists()) {
            // Reading the files of the directory:
            addDirContent(thridLevelDir);

            // Checking for the similar file:
            for (File file : readFiles) {
              System.out.println(file.getAbsolutePath());
              if (compareAcousticIds(new MusicFile(file.getAbsolutePath(), true), musicFile)
                  >= 90.0) {
                musicFile.setPossibleDuplicate(true);
                duplicate = true;
                break;
              } else if (file.getAbsolutePath().contains(titlename)) {
                duplicate = true;
                break;
              }
            }
          } else {
            // Reading the files of the directory:
            addDirContent(secondLevelDir);

            // Checking for the similar file:
            for (File file : readFiles) {
              if (compareAcousticIds(new MusicFile(file.getAbsolutePath(), true), musicFile)
                  >= 90.0) {
                musicFile.setPossibleDuplicate(true);
                duplicate = true;
                break;
              } else if (file.getAbsolutePath().contains(titlename)) {
                duplicate = true;
                break;
              }
            }
          }
        } else {
          duplicate = false;
        }
      } else {
        duplicate = false;
      }

      // Artist - Album
    } else {
      firstLevelDir_path =
          pathToLibrary
              + "\\"
              + artist.substring(0, 1).toUpperCase()
              + artist.substring(1, artist.length());
      secondLevelDir_path =
          firstLevelDir_path
              + "\\"
              + album.substring(0, 1).toUpperCase()
              + album.substring(1, album.length());

      // First checking whether there is a Directory for the music file
      firstLevelDir = new File(firstLevelDir_path);
      secondLevelDir = new File(secondLevelDir_path);

      // The artist subFolder exists
      if (firstLevelDir.exists()) {
        if (secondLevelDir.exists()) {
          // Reading the files of the directory:
          addDirContent(secondLevelDir);

          // Checking for the similar file:
          for (File file : readFiles) {

            // Compare the AcoustID's
            if (compareAcousticIds(new MusicFile(file.getAbsolutePath()), musicFile) >= 90.0) {
              musicFile.setPossibleDuplicate(true);
              duplicate = true;
              break;
            } else if (file.getAbsolutePath().contains(titlename)) {
              duplicate = true;
              break;
            }
          }
        } else {

          // Reading the files of the directory:
          addDirContent(firstLevelDir);

          // Checking for the similar file:
          for (File file : readFiles) {
            if (compareAcousticIds(new MusicFile(file.getAbsolutePath(), true), musicFile)
                >= 90.0) {
              musicFile.setPossibleDuplicate(true);
              duplicate = true;
              break;
            } else if (file.getAbsolutePath().contains(titlename)) {
              duplicate = true;
              break;
            }
          }
        }
      } else {
        duplicate = false;
      }
    }

    return duplicate;
  }
/** Helper class for all kinds of operations with music files */
public class MusicFileUtils {
  /** String that contains numbers (for ordering Mode 1) */
  private static final String NUMBERS = PropertiesUtils.getString("util.config.numbers");

  /** for bidden characters for the file/dir name */
  private static String[] forbiddenChars_1 =
      PropertiesUtils.getArray("util.config.forbidden.chars.1");
  /** valid characters for the file/dir name */
  private static String[] validChars = PropertiesUtils.getArray("util.config.valid.chars");
  /** forbidden characters for the file/dir name */
  private static String forbiddenChars_2 =
      PropertiesUtils.getString("util.config.forbidden.chars.2");

  private static ArrayList<File> readFiles = new ArrayList<File>();

  /**
   * Method for generating the new File name of the music file, after the tag was completed
   *
   * @param musicFile the music file
   * @return new Filename
   */
  public static void generateNewFileName(MusicFile musicFile) {
    MusicTag tag = musicFile.getTag();

    if (!tag.getArtist().equals("")
        && tag.getArtist() != null
        && !tag.getTitlename().equals("")
        && tag.getTitlename() != null) {
      // Clearing artist and title
      int track;
      try {
        track = Integer.parseInt(tag.getRelease().getTrackNumber());
      } catch (NumberFormatException e) {
        track = 0;
      }

      String artist = cleanString(tag.getArtist());
      String title = cleanString(tag.getTitlename());
      artist = clearForbiddenCharacters(artist);
      title = clearForbiddenCharacters(title);

      if (track != 0) {
        musicFile.setNewFileName(
            track
                + " - "
                + artist
                + " - "
                + title
                + "."
                + MusicFileType.getFileExtension(musicFile.getFileType()));
      } else {
        musicFile.setNewFileName(
            artist + " - " + title + "." + MusicFileType.getFileExtension(musicFile.getFileType()));
      }

      musicFile.setNewFileNameIsSet(true);
    } else {
      musicFile.setNewFileNameIsSet(false);
    }
  }

  /**
   * Method for making the directory for the imported file
   *
   * @param musicFile
   * @return path to the directory
   * @throws IOException
   */
  public static String makeFileDir(MusicFile musicFile) throws IOException {
    File level_1;
    File level_2;
    File level_3;

    String pathToMusicLibrary;

    pathToMusicLibrary = PropertiesUtils.getProperty(LibraryProperties.FILEPATH);
    OrderingProperty orderingMode = PropertiesUtils.getOrderingProperty();

    // Cleaning artist and album
    String artist = cleanString(musicFile.getTag().getArtist());
    String album = cleanString(musicFile.getTag().getAlbum());
    artist = clearForbiddenCharacters(artist);
    album = clearForbiddenCharacters(album);

    // Ordering: A - Artist - Album
    if (orderingMode == OrderingProperty.AAA) {
      if (NUMBERS.contains(artist.substring(0, 1))) {
        level_1 = new File(pathToMusicLibrary + "\\" + "123");
        level_2 = new File(pathToMusicLibrary + "\\" + "123" + "\\" + artist);
        level_3 = new File(pathToMusicLibrary + "\\" + "123" + "\\" + artist + "\\" + album);
      } else {
        level_1 = new File(pathToMusicLibrary + "\\" + artist.substring(0, 1).toUpperCase());
        level_2 =
            new File(
                pathToMusicLibrary
                    + "\\"
                    + artist.toUpperCase().substring(0, 1).toUpperCase()
                    + "\\"
                    + (artist.toUpperCase()).substring(0, 1).toUpperCase()
                    + artist.substring(1, artist.length()));
        level_3 =
            new File(
                pathToMusicLibrary
                    + "\\"
                    + artist.toUpperCase().substring(0, 1).toUpperCase()
                    + "\\"
                    + (artist.toUpperCase()).substring(0, 1).toUpperCase()
                    + artist.substring(1, artist.length())
                    + "\\"
                    + (album.toUpperCase()).substring(0, 1).toUpperCase()
                    + album.substring(1, album.length()));
      }

      if (level_1.exists() == false) {
        level_1.mkdir();
      }

      if (level_2.exists() == false) {
        level_2.mkdir();
      }

      if (level_3.exists() == false) {
        level_3.mkdir();
      }

      return level_3.getAbsolutePath();

      // Genre - Artist - Album
    } else if (orderingMode == OrderingProperty.GAA) {
      String genre = cleanString(musicFile.getTag().getGenre());
      genre = clearForbiddenCharacters(genre);

      level_1 =
          new File(
              pathToMusicLibrary
                  + "\\"
                  + genre.substring(0, 1).toUpperCase()
                  + genre.substring(1, genre.length()));
      level_2 =
          new File(
              pathToMusicLibrary
                  + "\\"
                  + genre.substring(0, 1).toUpperCase()
                  + genre.substring(1, genre.length())
                  + "\\"
                  + artist.substring(0, 1).toUpperCase()
                  + artist.substring(1, artist.length()));
      level_3 =
          new File(
              pathToMusicLibrary
                  + "\\"
                  + genre.substring(0, 1).toUpperCase()
                  + genre.substring(1, genre.length())
                  + "\\"
                  + artist.substring(0, 1).toUpperCase()
                  + artist.substring(1, artist.length())
                  + "\\"
                  + album.substring(0, 1).toUpperCase()
                  + album.substring(1, album.length()));

      if (level_1.exists() == false) {
        level_1.mkdir();
      }

      if (level_2.exists() == false) {
        level_2.mkdir();
      }

      if (level_3.exists() == false) {
        level_3.mkdir();
      }

      return level_3.getAbsolutePath();

      // Artist - Album
    } else if (orderingMode == OrderingProperty.AA) {
      level_1 =
          new File(
              pathToMusicLibrary
                  + "\\"
                  + artist.toUpperCase().charAt(0)
                  + artist.substring(1, artist.length()));
      level_2 =
          new File(
              pathToMusicLibrary
                  + "\\"
                  + artist.toUpperCase().charAt(0)
                  + artist.substring(1, artist.length())
                  + "\\"
                  + album.substring(0, 1).toUpperCase()
                  + album.substring(1, album.length()));

      if (level_1.exists() == false) {
        level_1.mkdir();
      }

      if (level_2.exists() == false) {
        level_2.mkdir();
      }

      return level_2.getAbsolutePath();
    }

    return "";
  }

  /**
   * Method for copying the music file to the new destination
   *
   * @param musicFile File to be copied
   * @param keep indicates whether the original file gets kept
   * @throws IOException
   */
  @SuppressWarnings("resource")
  public static void copyMusicFileToLibrary(MusicFile musicFile, Boolean keep) throws IOException {
    if (musicFile.isNewFileNameIsSet() && musicFile.isNewFilePathIsSet()) {
      File newFile_Dest = new File(musicFile.getNewFilePath() + "\\" + musicFile.getNewFileName());
      FileChannel inChannel = null;
      FileChannel outChannel = null;

      try {
        inChannel = new FileInputStream(new File(musicFile.getOriginalFilePath())).getChannel();
        outChannel = new FileOutputStream(newFile_Dest).getChannel();
        inChannel.transferTo(0, inChannel.size(), outChannel);
      } catch (IOException e) {
        e.printStackTrace();
      } finally {
        if (inChannel != null) inChannel.close();
        if (outChannel != null) outChannel.close();
      }

      if (!keep) {
        (new File(musicFile.getOriginalFilePath())).delete();
      }
    }
  }

  /**
   * Method for copying the music file to the new destination
   *
   * @param musicFile File to be copied
   * @param keep indicates whether the original file gets kept
   * @throws IOException
   */
  @SuppressWarnings("resource")
  public static void copyMusicFileToOther(MusicFile musicFile, String newDest) throws IOException {

    File newFile_Dest = new File(newDest + "//" + musicFile.getFile().getName());
    FileChannel inChannel = null;
    FileChannel outChannel = null;

    try {
      inChannel = new FileInputStream(new File(musicFile.getOriginalFilePath())).getChannel();
      outChannel = new FileOutputStream(newFile_Dest).getChannel();
      inChannel.transferTo(0, inChannel.size(), outChannel);

      musicFile.setOriginalFilePath(newFile_Dest.getAbsolutePath());
      musicFile.setFile(newFile_Dest);
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (inChannel != null) inChannel.close();
      if (outChannel != null) outChannel.close();
    }
  }

  /**
   * Method for copying the music file to the new destination
   *
   * @param musicFile File to be copied
   * @param keep indicates whether the original file gets kept
   * @param the new file name
   * @throws IOException
   */
  @SuppressWarnings("resource")
  public static void copyMusicFileToOther(MusicFile musicFile, String newDest, String newFileName)
      throws IOException {

    File newFile_Dest = new File(newDest + "//" + newFileName);
    FileChannel inChannel = null;
    FileChannel outChannel = null;

    try {
      inChannel = new FileInputStream(new File(musicFile.getOriginalFilePath())).getChannel();
      outChannel = new FileOutputStream(newFile_Dest).getChannel();
      inChannel.transferTo(0, inChannel.size(), outChannel);

      musicFile.setOriginalFilePath(newFile_Dest.getAbsolutePath());
      musicFile.setFile(newFile_Dest);
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (inChannel != null) inChannel.close();
      if (outChannel != null) outChannel.close();
    }
  }

  /**
   * Method for clearing the String from forbidden characters
   *
   * @param name
   * @return the cleared String
   */
  public static String clearForbiddenCharacters(String name) {
    for (int i = 0; i < forbiddenChars_1.length; i++) {
      name = name.replace(forbiddenChars_1[i], validChars[i]);
    }

    return name;
  }

  /**
   * Method for clearing the String from forbidden characters (changing German umlaute to the
   * equivalent...)
   *
   * @param name
   * @return the cleared String
   */
  public static String cleanString(String name) {
    for (int i = 0; i < forbiddenChars_2.length(); i++) {
      name = name.replace(forbiddenChars_2.substring(i, i + 1), "");
    }

    return name;
  }

  /**
   * Checks for a certain file if there is already a music file in the library
   *
   * @param musicFile to be checked
   * @return boolean indicating whether there is a duplicate already
   */
  public static boolean checkForDuplicates(MusicFile musicFile)
      throws CannotReadException, IOException, TagException, ReadOnlyFileException,
          InvalidAudioFrameException {
    // The Directories
    File firstLevelDir;
    File secondLevelDir;
    File thridLevelDir;

    // The direcotryPaths
    String firstLevelDir_path;
    String secondLevelDir_path;
    String thridLevelDir_path;

    // Clearing the readFiles list
    readFiles.clear();

    // Reading the tag
    MusicTag tag = musicFile.getTag();
    boolean duplicate = false;

    // Reading the path to the music library and ordering Mode
    String pathToLibrary = PropertiesUtils.getProperty(LibraryProperties.FILEPATH);
    OrderingProperty orderingMode = PropertiesUtils.getOrderingProperty();

    // Cleaning the Strings
    String artist =
        MusicFileUtils.clearForbiddenCharacters(MusicFileUtils.cleanString(tag.getArtist()));
    String album =
        MusicFileUtils.clearForbiddenCharacters(MusicFileUtils.cleanString(tag.getAlbum()));
    String titlename =
        MusicFileUtils.clearForbiddenCharacters(MusicFileUtils.cleanString(tag.getTitlename()));
    String genre =
        MusicFileUtils.clearForbiddenCharacters(MusicFileUtils.cleanString(tag.getGenre()));

    if (orderingMode == OrderingProperty.AAA || orderingMode == OrderingProperty.GAA) {
      // Building the Directorystrings
      // Ordering: A - Artist - Album
      if (orderingMode == OrderingProperty.AAA) {
        firstLevelDir_path = pathToLibrary + "\\" + artist.substring(0, 1).toUpperCase();
        secondLevelDir_path =
            firstLevelDir_path
                + "\\"
                + artist.substring(0, 1).toUpperCase()
                + artist.substring(1, artist.length());
        thridLevelDir_path =
            secondLevelDir_path
                + "\\"
                + album.substring(0, 1).toUpperCase()
                + album.substring(1, album.length());
        // Genre - Artist - Album
      } else {
        firstLevelDir_path =
            pathToLibrary
                + "\\"
                + genre.substring(0, 1).toUpperCase()
                + genre.substring(1, genre.length()).toUpperCase();
        secondLevelDir_path =
            firstLevelDir_path
                + "\\"
                + artist.substring(0, 1).toUpperCase()
                + artist.substring(1, artist.length());
        thridLevelDir_path =
            secondLevelDir_path
                + "\\"
                + album.substring(0, 1).toUpperCase()
                + album.substring(1, album.length());
      }

      // First checking whether there is a Directory for the music file
      firstLevelDir = new File(firstLevelDir_path);
      secondLevelDir = new File(secondLevelDir_path);
      thridLevelDir = new File(thridLevelDir_path);

      // The artist subFolder exists
      if (firstLevelDir.exists()) {
        if (secondLevelDir.exists()) {
          if (thridLevelDir.exists()) {
            // Reading the files of the directory:
            addDirContent(thridLevelDir);

            // Checking for the similar file:
            for (File file : readFiles) {
              System.out.println(file.getAbsolutePath());
              if (compareAcousticIds(new MusicFile(file.getAbsolutePath(), true), musicFile)
                  >= 90.0) {
                musicFile.setPossibleDuplicate(true);
                duplicate = true;
                break;
              } else if (file.getAbsolutePath().contains(titlename)) {
                duplicate = true;
                break;
              }
            }
          } else {
            // Reading the files of the directory:
            addDirContent(secondLevelDir);

            // Checking for the similar file:
            for (File file : readFiles) {
              if (compareAcousticIds(new MusicFile(file.getAbsolutePath(), true), musicFile)
                  >= 90.0) {
                musicFile.setPossibleDuplicate(true);
                duplicate = true;
                break;
              } else if (file.getAbsolutePath().contains(titlename)) {
                duplicate = true;
                break;
              }
            }
          }
        } else {
          duplicate = false;
        }
      } else {
        duplicate = false;
      }

      // Artist - Album
    } else {
      firstLevelDir_path =
          pathToLibrary
              + "\\"
              + artist.substring(0, 1).toUpperCase()
              + artist.substring(1, artist.length());
      secondLevelDir_path =
          firstLevelDir_path
              + "\\"
              + album.substring(0, 1).toUpperCase()
              + album.substring(1, album.length());

      // First checking whether there is a Directory for the music file
      firstLevelDir = new File(firstLevelDir_path);
      secondLevelDir = new File(secondLevelDir_path);

      // The artist subFolder exists
      if (firstLevelDir.exists()) {
        if (secondLevelDir.exists()) {
          // Reading the files of the directory:
          addDirContent(secondLevelDir);

          // Checking for the similar file:
          for (File file : readFiles) {

            // Compare the AcoustID's
            if (compareAcousticIds(new MusicFile(file.getAbsolutePath()), musicFile) >= 90.0) {
              musicFile.setPossibleDuplicate(true);
              duplicate = true;
              break;
            } else if (file.getAbsolutePath().contains(titlename)) {
              duplicate = true;
              break;
            }
          }
        } else {

          // Reading the files of the directory:
          addDirContent(firstLevelDir);

          // Checking for the similar file:
          for (File file : readFiles) {
            if (compareAcousticIds(new MusicFile(file.getAbsolutePath(), true), musicFile)
                >= 90.0) {
              musicFile.setPossibleDuplicate(true);
              duplicate = true;
              break;
            } else if (file.getAbsolutePath().contains(titlename)) {
              duplicate = true;
              break;
            }
          }
        }
      } else {
        duplicate = false;
      }
    }

    return duplicate;
  }

  /**
   * Method for comparing the acoustic fingerprint of two music files
   *
   * @param file1 first music file
   * @param file2 second music file
   * @return boolean indicating whether there is a duplicate already
   */
  public static double compareAcousticIds(MusicFile file1, MusicFile file2) {
    int minLength;

    if (file1.getChromaPrint() != null && file2.getChromaPrint() != null) {
      if (Integer.parseInt(file1.getChromaPrint().getDuration())
          >= Integer.parseInt(file2.getChromaPrint().getDuration())) {
        minLength = Integer.parseInt(file2.getChromaPrint().getDuration());
      } else {
        minLength = Integer.parseInt(file1.getChromaPrint().getDuration());
      }

      double score = 0.0;
      double scorePoint = 100.0 / minLength;

      char[] file1_fingerPrint = file1.getChromaPrint().getChromaprint().toCharArray();
      char[] file2_fingerPrint = file2.getChromaPrint().getChromaprint().toCharArray();

      for (int i = 0; i < minLength; i++) {
        if (file1_fingerPrint[i] == file2_fingerPrint[i]) {
          score += scorePoint;
        }
      }
      return score;
    }

    return 0.0;
  }

  /**
   * Method to read the music files from a directory and to store it in readFiles
   *
   * @param dir Directory which will be read
   */
  public static void addDirContent(File dir) {
    // Write Files to Array
    File[] files = dir.listFiles();

    if (files != null) {
      for (int i = 0; i < files.length; i++) {
        // Updating the Progress for the ProgressBar

        // In case the File is a Directory
        if (files[i].isDirectory()) {
          // Calling method recursively
          addDirContent(files[i]);
        } else {
          // Checking if the file is an music file
          boolean musicFile = checkIfMusicFile(files[i]);

          if (musicFile) {
            // Adding the music file to the array list
            readFiles.add(new File(files[i].getAbsolutePath()));
          }
        }
      }
    }
  }

  /**
   * Method to check whether the imported file is a music file
   *
   * @param file: imported file
   * @return true: the imported file is a music file and otherwise
   */
  public static boolean checkIfMusicFile(File file) {
    for (MusicFileType type : MusicFileType.values()) {
      if (file.getAbsolutePath().contains(MusicFileType.getFileExtension(type))) {
        return true;
      }
    }

    return false;
  }

  /**
   * Method to generate the new file path
   *
   * @throws IOException Gets thrown if the directory can't be made
   */
  public static void generateNewFilePath(MusicFile file) throws IOException {
    MusicTag tag = file.getTag();
    OrderingProperty orderingProperty = PropertiesUtils.getOrderingProperty();

    if (!tag.getArtist().equals("") && !tag.getAlbum().equals("")) {
      if (orderingProperty == OrderingProperty.GAA && !tag.getGenre().equals("")
          || orderingProperty == OrderingProperty.AA
          || orderingProperty == OrderingProperty.AAA) {
        file.setNewFilePathIsSet(true);
        file.setNewFilePath(MusicFileUtils.makeFileDir(file));
      } else {
        file.setNewFilePathIsSet(false);
        file.setNewFilePath("");
      }
    } else {
      file.setNewFilePathIsSet(false);
      file.setNewFilePath("");
    }
  }
}