/* (non-Javadoc)
  * @see org.jajuk.ui.actions.JajukAction#perform(java.awt.event.ActionEvent)
  */
 @Override
 @SuppressWarnings("unchecked")
 public void perform(ActionEvent e) {
   // TODO : rework this method into smaller units
   JComponent source = (JComponent) e.getSource();
   final List<Item> alSelected = (List<Item>) source.getClientProperty(Const.DETAIL_SELECTION);
   final List<Item> itemsToMove = ItemMoveManager.getInstance().getAll();
   final ItemMoveManager.MoveActions moveAction = ItemMoveManager.getInstance().getAction();
   final List<File> alFiles = new ArrayList<File>(alSelected.size());
   final List<Playlist> alPlaylists = new ArrayList<Playlist>(alSelected.size());
   final List<Directory> alDirs = new ArrayList<Directory>(alSelected.size());
   new Thread("Paste Thread") {
     @SuppressWarnings("cast")
     @Override
     public void run() {
       UtilGUI.waiting();
       // Compute all files to move from various items list
       if (itemsToMove.size() == 0) {
         Log.debug("None item to move");
         return;
       }
       Item first = itemsToMove.get(0);
       if (first instanceof Album || first instanceof Artist || first instanceof Genre) {
         List<Track> tracks = TrackManager.getInstance().getAssociatedTracks(itemsToMove, true);
         for (Track track : tracks) {
           alFiles.addAll(track.getFiles());
         }
       } else {
         for (Item item : itemsToMove) {
           if (item instanceof File) {
             alFiles.add((File) item);
           } else if (item instanceof Track) {
             alFiles.addAll(((Track) item).getFiles());
           } else if (item instanceof Directory) {
             alDirs.add((Directory) item);
           } else if (item instanceof Playlist) {
             alPlaylists.add((Playlist) item);
           }
         }
       }
       // Compute destination directory
       // alSelected can contain either a single Directory or a single Device
       Item item = alSelected.get(0);
       java.io.File dir;
       Directory destDir;
       if (item instanceof Directory) {
         dir = new java.io.File(((Directory) item).getAbsolutePath());
         destDir = (Directory) item;
       } else if (item instanceof Device) {
         dir = new java.io.File(((Device) item).getRootDirectory().getAbsolutePath());
         destDir = ((Device) item).getRootDirectory();
       } else {
         dir = ((File) item).getDirectory().getFio();
         destDir = ((File) item).getDirectory();
       }
       // Compute source directories
       // We need to find the highest directory in order to refresh it along
       // with the destination file to avoid phantom references
       List<Directory> srcDirs = new ArrayList<Directory>(1);
       for (File file : alFiles) {
         boolean parentAlreadyPresent = false;
         // We have to iterate using items index because the collection can
         // grow
         for (int i = 0; i < srcDirs.size(); i++) {
           Directory directory = (Directory) srcDirs.get(i);
           if (file.getDirectory().isChildOf(directory)) {
             parentAlreadyPresent = true;
             break;
           }
         }
         if (!parentAlreadyPresent && !srcDirs.contains(file.getDirectory())) {
           srcDirs.add(file.getDirectory());
         }
       }
       for (Playlist pl : alPlaylists) {
         boolean parentAlreadyPresent = false;
         // We have to iterate using items index because the collection can
         // grow
         for (int i = 0; i < srcDirs.size(); i++) {
           Directory directory = (Directory) srcDirs.get(i);
           if (pl.getDirectory().isChildOf(directory)) {
             parentAlreadyPresent = true;
             break;
           }
         }
         if (!parentAlreadyPresent && !srcDirs.contains(pl.getDirectory())) {
           srcDirs.add(pl.getDirectory());
         }
       }
       boolean overwriteAll = false;
       boolean bErrorOccured = false;
       if (moveAction == ItemMoveManager.MoveActions.CUT) {
         for (File f : alFiles) {
           if (!overwriteAll) {
             java.io.File newFile = new java.io.File(dir.getAbsolutePath() + "/" + f.getName());
             if (newFile.exists()) {
               int iResu =
                   Messages.getChoice(
                       Messages.getString("Confirmation_file_overwrite") + " : \n\n" + f.getName(),
                       Messages.YES_NO_ALL_CANCEL_OPTION,
                       JOptionPane.INFORMATION_MESSAGE);
               if (iResu == JOptionPane.NO_OPTION || iResu == JOptionPane.CANCEL_OPTION) {
                 UtilGUI.stopWaiting();
                 return;
               }
               if (iResu == Messages.ALL_OPTION) {
                 overwriteAll = true;
               }
             }
           }
           try {
             showMessage(f.getFIO());
             FileManager.getInstance().changeFileDirectory(f, destDir);
           } catch (Exception ioe) {
             Log.error(131, ioe);
             Messages.showErrorMessage(131);
             bErrorOccured = true;
           }
         }
         for (Playlist pl : alPlaylists) {
           if (!overwriteAll) {
             java.io.File newFile = new java.io.File(dir.getAbsolutePath() + "/" + pl.getName());
             if (newFile.exists()) {
               int iResu =
                   Messages.getChoice(
                       Messages.getString("Confirmation_file_overwrite")
                           + " : \n\n"
                           + pl.getName(),
                       Messages.YES_NO_ALL_CANCEL_OPTION,
                       JOptionPane.INFORMATION_MESSAGE);
               if (iResu == JOptionPane.NO_OPTION || iResu == JOptionPane.CANCEL_OPTION) {
                 UtilGUI.stopWaiting();
                 return;
               }
               if (iResu == Messages.ALL_OPTION) {
                 overwriteAll = true;
               }
             }
           }
           try {
             showMessage(pl.getFIO());
             final java.io.File fileNew =
                 new java.io.File(
                     new StringBuilder(dir.getAbsolutePath())
                         .append("/")
                         .append(pl.getName())
                         .toString());
             if (!pl.getFIO().renameTo(fileNew)) {
               throw new Exception(
                   "Cannot move item: "
                       + pl.getFIO().getAbsolutePath()
                       + " to "
                       + fileNew.getAbsolutePath());
             }
             // Refresh source and destination
             destDir.refresh(false);
             // Refresh source directories as well
             for (Directory srcDir : srcDirs) {
               srcDir.cleanRemovedFiles();
               srcDir.refresh(false);
             }
           } catch (Exception ioe) {
             Log.error(131, ioe);
             Messages.showErrorMessage(131);
             bErrorOccured = true;
           }
         }
         for (Directory d : alDirs) {
           try {
             java.io.File src = new java.io.File(d.getAbsolutePath());
             java.io.File dst = new java.io.File(dir.getAbsolutePath() + "/" + d.getName());
             showMessage(src);
             java.io.File newDir =
                 new java.io.File(new StringBuilder(dst.getAbsolutePath()).toString());
             if (!src.renameTo(newDir)) {
               throw new Exception(
                   "Cannot move item: " + src.getAbsolutePath() + " to " + dst.getAbsolutePath());
             }
             DirectoryManager.getInstance().removeDirectory(d.getID());
             destDir.refresh(false);
           } catch (Exception ioe) {
             Log.error(131, ioe);
             Messages.showErrorMessage(131);
             bErrorOccured = true;
           }
         }
         try {
           destDir.refresh(false);
           // Refresh source directories as well
           for (Directory srcDir : srcDirs) {
             srcDir.refresh(false);
           }
         } catch (Exception e1) {
           Log.error(e1);
           bErrorOccured = true;
         }
       } else if (moveAction == ItemMoveManager.MoveActions.COPY) {
         for (File f : alFiles) {
           if (!overwriteAll) {
             java.io.File newFile = new java.io.File(dir.getAbsolutePath() + "/" + f.getName());
             if (newFile.exists()) {
               int iResu =
                   Messages.getChoice(
                       Messages.getString("Confirmation_file_overwrite") + " : \n\n" + f.getName(),
                       Messages.YES_NO_ALL_CANCEL_OPTION,
                       JOptionPane.INFORMATION_MESSAGE);
               if (iResu == JOptionPane.NO_OPTION || iResu == JOptionPane.CANCEL_OPTION) {
                 UtilGUI.stopWaiting();
                 return;
               }
               if (iResu == Messages.ALL_OPTION) {
                 overwriteAll = true;
               }
             }
           }
           try {
             showMessage(f.getFIO());
             UtilSystem.copyToDir(f.getFIO(), dir);
           } catch (Exception ioe) {
             Log.error(131, ioe);
             Messages.showErrorMessage(131);
             bErrorOccured = true;
           }
         }
         for (Playlist pl : alPlaylists) {
           if (!overwriteAll) {
             java.io.File newFile = new java.io.File(dir.getAbsolutePath() + "/" + pl.getName());
             if (newFile.exists()) {
               int iResu =
                   Messages.getChoice(
                       Messages.getString("Confirmation_file_overwrite")
                           + " : \n\n"
                           + pl.getName(),
                       Messages.YES_NO_ALL_CANCEL_OPTION,
                       JOptionPane.INFORMATION_MESSAGE);
               if (iResu == JOptionPane.NO_OPTION || iResu == JOptionPane.CANCEL_OPTION) {
                 UtilGUI.stopWaiting();
                 return;
               }
               if (iResu == Messages.ALL_OPTION) {
                 overwriteAll = true;
               }
             }
           }
           try {
             showMessage(pl.getFIO());
             UtilSystem.copyToDir(pl.getFIO(), dir);
             // Refresh source and destination
             destDir.refresh(false);
             // Refresh source directories as well
             for (Directory srcDir : srcDirs) {
               srcDir.refresh(false);
             }
           } catch (Exception ioe) {
             Log.error(131, ioe);
             Messages.showErrorMessage(131);
             bErrorOccured = true;
           }
         }
         for (Directory d : alDirs) {
           try {
             java.io.File src = new java.io.File(d.getAbsolutePath());
             java.io.File dst = new java.io.File(dir.getAbsolutePath() + "/" + d.getName());
             showMessage(src);
             UtilSystem.copyRecursively(src, dst);
           } catch (Exception ioe) {
             Log.error(131, ioe);
             Messages.showErrorMessage(131);
             bErrorOccured = true;
           }
         }
         try {
           destDir.refresh(false);
         } catch (Exception e1) {
           Log.error(e1);
           bErrorOccured = true;
         }
       }
       ObservationManager.notify(new JajukEvent(JajukEvents.DEVICE_REFRESH));
       UtilGUI.stopWaiting();
       if (!bErrorOccured) {
         InformationJPanel.getInstance()
             .setMessage(Messages.getString("Success"), InformationJPanel.MessageType.INFORMATIVE);
       }
     }
   }.start();
 }