package de.onyxbits.raccoon.gui;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;

import javax.swing.JButton;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;


import com.akdeniz.googleplaycrawler.GooglePlay.DocV2;
import com.akdeniz.googleplaycrawler.GooglePlayAPI;

import de.onyxbits.raccoon.App;
import de.onyxbits.raccoon.io.Archive;

class DownloadWorker extends SwingWorker<Exception, Integer> {

	private Archive archive;
	private DocV2 app;
	protected JProgressBar progress;
	protected JButton cancel;

	public DownloadWorker(DocV2 app, Archive archive) {
		this.app = app;
		this.archive = archive;
		this.progress = new JProgressBar(0, 100);
		this.cancel = new JButton("Cancel");
		this.progress.setStringPainted(true);
	}

	@Override
	protected void process(List<Integer> chunks) {
		if (!isCancelled()) {
			int val = chunks.get(chunks.size() - 1);
			progress.setValue(chunks.get(chunks.size() - 1));
			progress.setString(val + "%");
		}
	}

	@Override
	protected Exception doInBackground() throws Exception {
		publish(0); // Just so there is no delay in the UI updating

		GooglePlayAPI service = App.createConnection(archive);
		String pn = app.getBackendDocid();
		int vc = app.getDetails().getAppDetails().getVersionCode();
		int ot = app.getOffer(0).getOfferType();
		long size = app.getDetails().getAppDetails().getInstallationSize();
		long complete = 0;
		InputStream in = service.download(pn, vc, ot);

		File dest = archive.fileUnder(pn, vc);
		dest.getParentFile().mkdirs();
		FileOutputStream out = new FileOutputStream(dest);
		byte[] buffer = new byte[1024 * 16];
		int length;
		while ((length = in.read(buffer)) > 0) {
			complete += length;
			out.write(buffer, 0, length);
			float percent = (float) complete / (float) size;
			publish((int) (100f * percent));
			if (isCancelled()) {
				out.close();
				in.close();
				dest.delete();
				return null;
			}
		}
		out.close();
		in.close();
		archive.getDownloadLogger().addEntry(dest);

		return null;
	}

	@Override
	protected void done() {
		progress.setString("Complete");
		try {
			get();
		}
		catch (CancellationException e) {
			progress.setString("Aborted");
		}
		catch (ExecutionException e) {
			progress.setString("Error!");
			e.printStackTrace();
		}
		catch (InterruptedException e) {
			progress.setString("Aborted");
		}
		cancel.setEnabled(false);
	}

}

@@ -31,90 +31,8 @@
 i;%0A%0A
-import java.io.File;%0Aimport java.io.FileOutputStream;%0Aimport java.io.InputStream;%0A
 impo
@@ -244,17 +244,16 @@
 orker;%0A%0A
-%0A
 import c
@@ -310,53 +310,39 @@
 ort 
-com.akdeniz.googleplaycrawler.GooglePlayAPI;%0A
+de.onyxbits.raccoon.io.Archive;
 %0Aimp
@@ -365,19 +365,32 @@
 raccoon.
-App
+io.FetchListener
 ;%0Aimport
@@ -413,22 +413,27 @@
 coon.io.
-Archiv
+FetchServic
 e;%0A%0Aclas
@@ -488,16 +488,41 @@
 Integer%3E
+ implements FetchListener
  %7B%0A%0A%09pri
@@ -625,16 +625,71 @@
 ancel;%0A%0A
+%09private long totalBytes;%0A%09private Exception failure;%0A%0A
 %09public 
@@ -1259,66 +1259,8 @@
 ting
-%0A%0A%09%09GooglePlayAPI service = App.createConnection(archive);
 %0A%09%09S
@@ -1404,17 +1404,18 @@
 ;%0A%09%09
-long size
+totalBytes
  = a
@@ -1475,621 +1475,58 @@
 ;%0A%09%09
-long complete = 0;%0A%09%09InputStream in = service.download(pn, vc, ot);%0A%0A%09%09File dest = archive.fileUnder(pn, vc);%0A%09%09dest.getParentFile().mkdirs();%0A%09%09FileOutputStream out = new FileOutputStream(dest);%0A%09%09byte%5B%5D buffer = new byte%5B1024 * 16%5D;%0A%09%09int length;%0A%09%09while ((length = in.read(buffer)) %3E 0) %7B%0A%09%09%09complete += length;%0A%09%09%09out.write(buffer, 0, length);%0A%09%09%09float percent = (float) complete / (float) size;%0A%09%09%09publish((int) (100f * percent));%0A%09%09%09if (isCancelled()) %7B%0A%09%09%09%09out.close();%0A%09%09%09%09in.close();%0A%09%09%09%09dest.delete();%0A%09%09%09%09return null;%0A%09%09%09%7D%0A%09%09%7D%0A%09%09out.close();%0A%09%09in.close();%0A%09%09archive.getDownloadLogger().addEntry(dest);%0A
+new FetchService(archive, pn, vc, ot, this).run();
 %0A%09%09r
@@ -1625,24 +1625,89 @@
 %7B%0A%09%09%09get();%0A
+%09%09%09if (failure!=null) %7B%0A%09%09%09%09progress.setString(%22Failure!%22);%0A%09%09%09%7D%0A
 %09%09%7D%0A%09%09catch 
@@ -1749,37 +1749,39 @@
 ress.setString(%22
-Abort
+Cancell
 ed%22);%0A%09%09%7D%0A%09%09catc
@@ -1973,10 +1973,295 @@
 e);%0A%09%7D%0A%0A
+%09public boolean onChunk(Object src, long numBytes) %7B%0A%09%09float percent = (float) numBytes / (float) totalBytes;%0A%09%09publish((int) (100f * percent));%0A%09%09return isCancelled();%0A%09%7D%0A%0A%09public void onComplete(Object src) %7B%0A%0A%09%7D%0A%0A%09public void onFailure(Object src, Exception e) %7B%0A%09%09failure = e;%0A%09%7D%0A%0A
 %7D%0A

Use FetchService as backend