/**
  * Returns whether a backup exists in the same folder as the specified resource entry or a biffed
  * file has been overriden.
  */
 static boolean isBackupAvailable(ResourceEntry entry) {
   if (entry != null) {
     return (getBackupFile(entry) != null
         || (entry instanceof BIFFResourceEntry && entry.hasOverride()));
   }
   return false;
 }
 // Returns the actual physical file of the given resource entry or null.
 private static Path getCurrentFile(ResourceEntry entry) {
   if (entry instanceof FileResourceEntry
       || (entry instanceof BIFFResourceEntry && entry.hasOverride())) {
     return entry.getActualPath();
   } else {
     return null;
   }
 }
 @Override
 public void show(Component invoker, int x, int y) {
   super.show(invoker, x, y);
   mi_rename.setEnabled(tree.getLastSelectedPathComponent() instanceof FileResourceEntry);
   if (tree.getLastSelectedPathComponent() instanceof ResourceEntry) {
     ResourceEntry entry = (ResourceEntry) tree.getLastSelectedPathComponent();
     mi_delete.setEnabled(
         entry != null && entry.hasOverride() || entry instanceof FileResourceEntry);
     mi_restore.setEnabled(isBackupAvailable(entry));
   } else {
     mi_delete.setEnabled(false);
     mi_restore.setEnabled(false);
   }
 }
 // Returns the backup file of the specified resource entry if available or null.
 // A backup file is either a *.bak file or a biffed file which has been overridden.
 private static Path getBackupFile(ResourceEntry entry) {
   Path file = getCurrentFile(entry);
   if (entry instanceof FileResourceEntry
       || (entry instanceof BIFFResourceEntry && entry.hasOverride())) {
     if (file != null) {
       Path bakFile = file.getParent().resolve(file.getFileName().toString() + ".bak");
       if (Files.isRegularFile(bakFile)) {
         return bakFile;
       }
     }
   } else if (entry instanceof BIFFResourceEntry) {
     return file;
   }
   return null;
 }
 /**
  * Attempts to restore the specified resource entry if it's backed up by an associated "*.bak"
  * file.
  */
 static void restoreResource(ResourceEntry entry) {
   if (entry != null) {
     final String[] options = {"Restore", "Cancel"};
     final String msgBackup =
         "Are you sure you want to restore " + entry + " with a previous version?";
     final String msgBiffed =
         "Are you sure you want to restore the biffed version of " + entry + "?";
     Path bakFile = getBackupFile(entry);
     boolean isBackedUp =
         (bakFile != null)
             && (bakFile.getFileName().toString().toLowerCase(Locale.ENGLISH).endsWith(".bak"));
     if (JOptionPane.showOptionDialog(
             NearInfinity.getInstance(),
             isBackedUp ? msgBackup : msgBiffed,
             "Restore backup",
             JOptionPane.YES_NO_OPTION,
             JOptionPane.QUESTION_MESSAGE,
             null,
             options,
             options[0])
         == JOptionPane.YES_OPTION) {
       NearInfinity.getInstance().removeViewable();
       if (bakFile != null
           && (bakFile.getFileName().toString().toLowerCase(Locale.ENGLISH).endsWith(".bak"))) {
         // .bak available -> restore .bak version
         Path curFile = getCurrentFile(entry);
         Path tmpFile = getTempFile(curFile);
         if (curFile != null
             && Files.isRegularFile(curFile)
             && bakFile != null
             && Files.isRegularFile(bakFile)) {
           try {
             Files.move(curFile, tmpFile);
             try {
               Files.move(bakFile, curFile);
               try {
                 Files.delete(tmpFile);
               } catch (IOException e) {
                 e.printStackTrace();
               }
               JOptionPane.showMessageDialog(
                   NearInfinity.getInstance(),
                   "Backup has been restored successfully.",
                   "Restore backup",
                   JOptionPane.INFORMATION_MESSAGE);
               return;
             } catch (IOException e) {
               // Worst possible scenario: failed restore operation can't restore original resource
               String path = tmpFile.getParent().toString();
               String tmpName = tmpFile.getFileName().toString();
               String curName = curFile.getFileName().toString();
               JOptionPane.showMessageDialog(
                   NearInfinity.getInstance(),
                   "Error while restoring resource.\n"
                       + "Near Infinity is unable to recover from the restore operation.\n"
                       + String.format(
                           "Please manually rename the file \"%1$s\" into \"%2$s\", located in \n + \"%3$s\"",
                           tmpName, curName, path),
                   "Critical Error",
                   JOptionPane.ERROR_MESSAGE);
               e.printStackTrace();
               return;
             }
           } catch (IOException e) {
             e.printStackTrace();
           }
         }
         JOptionPane.showMessageDialog(
             NearInfinity.getInstance(),
             "Error while restoring resource.\nRestore operation has been cancelled.",
             "Error",
             JOptionPane.ERROR_MESSAGE);
       } else if (entry instanceof BIFFResourceEntry && entry.hasOverride()) {
         // Biffed and no .bak available -> delete overridden copy
         try {
           ((BIFFResourceEntry) entry).deleteOverride();
           JOptionPane.showMessageDialog(
               NearInfinity.getInstance(),
               "Backup has been restored successfully.",
               "Restore backup",
               JOptionPane.INFORMATION_MESSAGE);
         } catch (IOException e) {
           JOptionPane.showMessageDialog(
               NearInfinity.getInstance(),
               "Error removing file \"" + entry + "\" from override folder!",
               "Error",
               JOptionPane.ERROR_MESSAGE);
           e.printStackTrace();
         }
       }
     }
   }
 }