package de.dal33t.powerfolder.ui.model;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.swing.SwingUtilities;
import de.dal33t.powerfolder.Controller;
import de.dal33t.powerfolder.disk.Folder;
import de.dal33t.powerfolder.disk.FolderRepository;
import de.dal33t.powerfolder.event.FolderAdapter;
import de.dal33t.powerfolder.event.FolderEvent;
import de.dal33t.powerfolder.event.FolderRepositoryEvent;
import de.dal33t.powerfolder.event.FolderRepositoryListener;
import de.dal33t.powerfolder.event.ListenerSupportFactory;
import de.dal33t.powerfolder.event.NodeManagerAdapter;
import de.dal33t.powerfolder.event.NodeManagerEvent;
import de.dal33t.powerfolder.event.OverallFolderStatListener;
import de.dal33t.powerfolder.event.TransferManagerEvent;
import de.dal33t.powerfolder.event.TransferManagerListener;
import de.dal33t.powerfolder.light.FolderInfo;
import de.dal33t.powerfolder.transfer.TransferManager;
import de.dal33t.powerfolder.ui.PFUIComponent;
public class FolderRepositoryModel extends PFUIComponent {
private final MyFolderListener folderListener;
private final OverallFolderStatListener overallFolderStatListenerSupport;
private boolean syncing = false;
private Date lastSyncDate = null;
private Date estimatedSyncDate = null;
private double overallSyncPercentage = 0;
/**
* List of folders where the user has requested a scan. Used to advise the
* UI when the next scan arrives so that the user can be notified.
*/
private final List<FolderInfo> interestedFolders = new ArrayList<FolderInfo>();
FolderRepositoryModel(Controller controller) {
super(controller);
folderListener = new MyFolderListener();
overallFolderStatListenerSupport = ListenerSupportFactory
.createListenerSupport(OverallFolderStatListener.class);
calculateOverallStats();
FolderRepository repo = controller.getFolderRepository();
for (Folder folder : repo.getFolders(true)) {
folder.addFolderListener(folderListener);
}
controller.getFolderRepository().addFolderRepositoryListener(
new MyFolderRepositoryListener());
controller.getTransferManager().addListener(
new MyTransferManagerListener());
controller.getNodeManager().addNodeManagerListener(
new MyNodeManagerListener());
}
public void addOverallFolderStatListener(OverallFolderStatListener listener)
{
ListenerSupportFactory.addListener(overallFolderStatListenerSupport,
listener);
}
public void removeOverallFolderStatListener(
OverallFolderStatListener listener)
{
ListenerSupportFactory.removeListener(overallFolderStatListenerSupport,
listener);
}
public boolean isSyncing() {
return syncing;
}
public Date getLastSyncDate() {
return lastSyncDate;
}
public Date getEstimatedSyncDate() {
return estimatedSyncDate;
}
/**
* @return -1 for not known yet
*/
public double getOverallSyncPercentage() {
return overallSyncPercentage;
}
/**
* When a folder updates its stats, check all folders to get whether any
* folders are syncing and what the greatest estimated / last sync date is.
*/
private void calculateOverallStats() {
// Find the folder with the most recent synchronized date / most
// future estimated date.
boolean localSyncing = false;
Date localLastSyncDate = null;
Date localEstimatedSyncDate = null;
double localOverallSyncPercentage = 0;
long totalSize = 0;
for (Folder folder : getController().getFolderRepository().getFolders(
true))
{
if (folder.isSyncing()) {
localSyncing = true;
}
Date tmpLastSync = folder.getLastSyncDate();
Date tmpEstimatedDate = folder.getStatistic()
.getEstimatedSyncDate();
if (tmpLastSync != null) {
if (localLastSyncDate == null
|| tmpLastSync.after(localLastSyncDate))
{
localLastSyncDate = tmpLastSync;
}
}
if (tmpEstimatedDate != null) {
if (localEstimatedSyncDate == null
|| tmpEstimatedDate.after(localEstimatedSyncDate))
{
localEstimatedSyncDate = tmpEstimatedDate;
}
}
double syncPercentage = folder.getStatistic()
.getHarmonizedSyncPercentage();
if (syncPercentage > 0) {
totalSize += folder.getStatistic().getTotalSize();
localOverallSyncPercentage += syncPercentage
* folder.getStatistic().getTotalSize();
}
}
if (totalSize == 0) {
localOverallSyncPercentage = 0;
} else {
localOverallSyncPercentage /= totalSize;
}
if (!getController().getOSClient().getServer().isCompletelyConnected())
{
localOverallSyncPercentage = -1;
}
// Update with the latest values.
syncing = localSyncing;
lastSyncDate = localLastSyncDate;
estimatedSyncDate = localEstimatedSyncDate;
overallSyncPercentage = localOverallSyncPercentage;
// Let everyone know.
overallFolderStatListenerSupport.statCalculated();
}
public void addInterestedFolderInfo(FolderInfo info) {
synchronized (interestedFolders) {
interestedFolders.add(info);
}
}
public void removeInterestedFolderInfo(FolderInfo info) {
synchronized (interestedFolders) {
interestedFolders.remove(info);
}
}
private class MyFolderRepositoryListener implements
FolderRepositoryListener
{
public void folderCreated(FolderRepositoryEvent e) {
e.getFolder().addFolderListener(folderListener);
}
public void folderRemoved(FolderRepositoryEvent e) {
e.getFolder().removeFolderListener(folderListener);
}
public void maintenanceFinished(FolderRepositoryEvent e) {
calculateOverallStats();
}
public void maintenanceStarted(FolderRepositoryEvent e) {
calculateOverallStats();
}
public boolean fireInEventDispatchThread() {
return false;
}
}
private class MyFolderListener extends FolderAdapter {
public void statisticsCalculated(FolderEvent folderEvent) {
calculateOverallStats();
}
public void scanResultCommited(final FolderEvent folderEvent) {
if (folderEvent.getScanResult().isChangeDetected()) {
calculateOverallStats();
}
FolderInfo folderInfo = folderEvent.getFolder().getInfo();
synchronized (interestedFolders) {
if (interestedFolders.contains(folderInfo)) {
// Give user feedback on this scan result.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
getUIController().scanResultCreated(
folderEvent.getScanResult());
}
});
interestedFolders.remove(folderInfo);
}
}
}
public boolean fireInEventDispatchThread() {
return false;
}
}
private class MyTransferManagerListener implements TransferManagerListener {
private TransferManager tm;
public MyTransferManagerListener() {
super();
this.tm = getController().getTransferManager();
}
public boolean fireInEventDispatchThread() {
return false;
}
public void downloadRequested(TransferManagerEvent event) {
}
public void downloadQueued(TransferManagerEvent event) {
}
public void downloadStarted(TransferManagerEvent event) {
calculateOverallStats();
}
public void downloadAborted(TransferManagerEvent event) {
calculateOverallStats();
}
public void downloadBroken(TransferManagerEvent event) {
calculateOverallStats();
}
public void downloadCompleted(TransferManagerEvent event) {
calculateOverallStats();
}
public void completedDownloadRemoved(TransferManagerEvent event) {
}
public void pendingDownloadEnqueued(TransferManagerEvent event) {
}
public void uploadRequested(TransferManagerEvent event) {
}
public void uploadStarted(TransferManagerEvent event) {
calculateOverallStats();
}
public void uploadAborted(TransferManagerEvent event) {
calculateOverallStats();
}
public void uploadBroken(TransferManagerEvent event) {
calculateOverallStats();
}
public void uploadCompleted(TransferManagerEvent event) {
calculateOverallStats();
}
public void completedUploadRemoved(TransferManagerEvent event) {
}
}
private class MyNodeManagerListener extends NodeManagerAdapter {
@Override
public void nodeConnecting(NodeManagerEvent e) {
if (e.getNode().hasJoinedAnyFolder()) {
calculateOverallStats();
}
}
@Override
public void nodeDisconnected(NodeManagerEvent e) {
if (e.getNode().hasJoinedAnyFolder()) {
calculateOverallStats();
}
}
public boolean fireInEventDispatchThread() {
return false;
}
}
}