/**
   * Check can write to file
   *
   * @param file
   * @throws IOException
   */
  public void precheck(File file) throws IOException {
    if (!file.exists()) {
      logger.severe(
          ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE_FILE_NOT_FOUND.getMsg(file.getName()));
      throw new IOException(
          ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE_FILE_NOT_FOUND.getMsg(file.getName()));
    }

    if (!file.canWrite()) {
      logger.severe(ErrorMessage.GENERAL_WRITE_FAILED.getMsg(file.getName()));
      throw new IOException(ErrorMessage.GENERAL_WRITE_FAILED.getMsg(file.getName()));
    }

    if (file.length() <= MINIMUM_FILESIZE) {
      logger.severe(
          ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE_FILE_IS_TOO_SMALL.getMsg(file.getName()));
      throw new IOException(
          ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE_FILE_IS_TOO_SMALL.getMsg(file.getName()));
    }
  }
  /**
   * Saves the tags in this dataType to the file argument. It will be saved as
   * TagConstants.MP3_FILE_SAVE_WRITE
   *
   * @param fileToSave file to save the this dataTypes tags to
   * @throws FileNotFoundException if unable to find file
   * @throws IOException on any I/O error
   */
  public void save(File fileToSave) throws IOException {
    // Ensure we are dealing with absolute filepaths not relative ones
    File file = fileToSave.getAbsoluteFile();

    logger.config("Saving  : " + file.getPath());

    // Checks before starting write
    precheck(file);

    RandomAccessFile rfile = null;
    try {
      // ID3v2 Tag
      if (TagOptionSingleton.getInstance().isId3v2Save()) {
        if (id3v2tag == null) {
          rfile = new RandomAccessFile(file, "rw");
          (new ID3v24Tag()).delete(rfile);
          (new ID3v23Tag()).delete(rfile);
          (new ID3v22Tag()).delete(rfile);
          logger.config("Deleting ID3v2 tag:" + file.getName());
          rfile.close();
        } else {
          logger.config("Writing ID3v2 tag:" + file.getName());
          final MP3AudioHeader mp3AudioHeader = (MP3AudioHeader) this.getAudioHeader();
          final long mp3StartByte = mp3AudioHeader.getMp3StartByte();
          final long newMp3StartByte = id3v2tag.write(file, mp3StartByte);
          if (mp3StartByte != newMp3StartByte) {
            logger.config("New mp3 start byte: " + newMp3StartByte);
            mp3AudioHeader.setMp3StartByte(newMp3StartByte);
          }
        }
      }
      rfile = new RandomAccessFile(file, "rw");

      // Lyrics 3 Tag
      if (TagOptionSingleton.getInstance().isLyrics3Save()) {
        if (lyrics3tag != null) {
          lyrics3tag.write(rfile);
        }
      }
      // ID3v1 tag
      if (TagOptionSingleton.getInstance().isId3v1Save()) {
        logger.config("Processing ID3v1");
        if (id3v1tag == null) {
          logger.config("Deleting ID3v1");
          (new ID3v1Tag()).delete(rfile);
        } else {
          logger.config("Saving ID3v1");
          id3v1tag.write(rfile);
        }
      }
    } catch (FileNotFoundException ex) {
      logger.log(
          Level.SEVERE,
          ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE_FILE_NOT_FOUND.getMsg(file.getName()),
          ex);
      throw ex;
    } catch (IOException iex) {
      logger.log(
          Level.SEVERE,
          ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE.getMsg(file.getName(), iex.getMessage()),
          iex);
      throw iex;
    } catch (RuntimeException re) {
      logger.log(
          Level.SEVERE,
          ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE.getMsg(file.getName(), re.getMessage()),
          re);
      throw re;
    } finally {
      if (rfile != null) {
        rfile.close();
      }
    }
  }