package freenet.clients.http.updateableelements;
import java.text.NumberFormat;
import freenet.client.FetchContext;
import freenet.clients.http.FProxyFetchInProgress;
import freenet.clients.http.FProxyFetchResult;
import freenet.clients.http.FProxyFetchTracker;
import freenet.clients.http.FProxyFetchWaiter;
import freenet.clients.http.SimpleToadletServer;
import freenet.clients.http.ToadletContext;
import freenet.keys.FreenetURI;
import freenet.l10n.NodeL10n;
import freenet.support.Base64;
import freenet.support.HTMLNode;
/** A pushed element that renders the progress bar when loading a page. */
public class ProgressBarElement extends BaseUpdateableElement {
/** The tracker that the Fetcher can be acquired */
private final FProxyFetchTracker tracker;
/** The URI of the download this progress bar shows */
private final FreenetURI key;
/** The maxSize */
private final long maxSize;
/** The FetchListener that gets notified when the download progresses */
private final NotifierFetchListener fetchListener;
private final FetchContext fctx;
public ProgressBarElement(FProxyFetchTracker tracker, FreenetURI key, FetchContext fctx, long maxSize, ToadletContext ctx, boolean pushed) {
// This is a <div>
super("div", "class", "progressbar", ctx);
this.tracker = tracker;
this.key = key;
this.fctx = fctx;
this.maxSize = maxSize;
init(pushed);
if(!pushed) {
fetchListener = null;
return;
}
// Creates and registers the FetchListener
fetchListener = new NotifierFetchListener(((SimpleToadletServer) ctx.getContainer()).pushDataManager, this);
tracker.getFetchInProgress(key, maxSize, fctx).addListener(fetchListener);
}
@Override
public void updateState(boolean initial) {
children.clear();
FProxyFetchInProgress progress = tracker.getFetchInProgress(key, maxSize, fctx);
FProxyFetchWaiter waiter = progress == null ? null : progress.getWaiter();
FProxyFetchResult fr = waiter == null ? null : waiter.getResult();
if (fr == null) {
addChild("div", "No fetcher found");
} else {
if (fr.isFinished() || fr.hasData() || fr.failed != null) {
// If finished then we just send a FINISHED text. It will reload the page
setContent(UpdaterConstants.FINISHED);
} else {
int total = fr.requiredBlocks;
int fetchedPercent = (int) (fr.fetchedBlocks / (double) total * 100);
int failedPercent = (int) (fr.failedBlocks / (double) total * 100);
int fatallyFailedPercent = (int) (fr.fatallyFailedBlocks / (double) total * 100);
HTMLNode progressBar = addChild("div", "class", "progressbar");
progressBar.addChild("div", new String[] { "class", "style" }, new String[] { "progressbar-done", "width: " + fetchedPercent + "%;" });
if (fr.failedBlocks > 0)
progressBar.addChild("div", new String[] { "class", "style" }, new String[] { "progressbar-failed", "width: " + failedPercent + "%;" });
if (fr.fatallyFailedBlocks > 0)
progressBar.addChild("div", new String[] { "class", "style" }, new String[] { "progressbar-failed2", "width: " + fatallyFailedPercent + "%;" });
NumberFormat nf = NumberFormat.getInstance();
nf.setMaximumFractionDigits(1);
String prefix = '('+Integer.toString(fr.fetchedBlocks) + "/ " + Integer.toString(total)+"): ";
if (fr.finalizedBlocks) {
progressBar.addChild("div", new String[] { "class", "title" }, new String[] { "progress_fraction_finalized", prefix + NodeL10n.getBase().getString("QueueToadlet.progressbarAccurate") }, nf.format((int) ((fr.fetchedBlocks / (double) total) * 1000) / 10.0) + '%');
} else {
String text = nf.format((int) ((fr.fetchedBlocks / (double) total) * 1000) / 10.0)+ '%';
text = "" + fr.fetchedBlocks + " ("+text+"??)";
progressBar.addChild("div", new String[] { "class", "title" }, new String[] { "progress_fraction_not_finalized", prefix + NodeL10n.getBase().getString("QueueToadlet.progressbarNotAccurate") }, text);
}
}
}
if (waiter != null) {
progress.close(waiter);
}
if (fr != null) {
progress.close(fr);
}
}
@Override
public String getUpdaterId(String requestId) {
return getId(key);
}
public static String getId(FreenetURI uri) {
return Base64.encodeStandardUTF8(("progressbar[URI:" + uri.toString() + "]"));
}
@Override
public void dispose() {
// Deregisters the FetchListener
FProxyFetchInProgress progress = tracker.getFetchInProgress(key, maxSize, fctx);
if (progress != null) {
progress.removeListener(fetchListener);
}
}
@Override
public String getUpdaterType() {
return UpdaterConstants.PROGRESSBAR_UPDATER;
}
@Override
public String toString() {
return "ProgressBarElement[key:" + key + ",maxSize:" + maxSize + ",updaterId:" + getUpdaterId(null) + "]";
}
}