package tim.prune.function.srtm;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import javax.swing.JOptionPane;
import tim.prune.App;
import tim.prune.GenericFunction;
import tim.prune.GpsPrune;
import tim.prune.I18nManager;
import tim.prune.config.Config;
import tim.prune.data.DoubleRange;
import tim.prune.gui.ProgressDialog;
/**
* Class to provide a download function for the Space Shuttle's SRTM data files.
* HGT files are downloaded into memory via HTTP and stored in the map cache.
*/
public class DownloadSrtmFunction extends GenericFunction implements Runnable
{
/** Progress dialog */
private ProgressDialog _progress = null;
/** Flag to check whether this function is currently running or not */
private boolean _running = false;
/**
* Constructor
* @param inApp App object
*/
public DownloadSrtmFunction(App inApp) {
super(inApp);
}
/** @return name key */
public String getNameKey() {
return "function.downloadsrtm";
}
/**
* Begin the download
*/
public void begin()
{
_running = true;
if (_progress == null) {
_progress = new ProgressDialog(_parentFrame, getNameKey());
}
_progress.show();
// start new thread for time-consuming part
new Thread(this).start();
}
/**
* Run method using separate thread
*/
public void run()
{
// Compile list of tiles to get
ArrayList<SrtmTile> tileList = new ArrayList<SrtmTile>();
// First, loop to see which tiles are needed
DoubleRange lonRange = _app.getTrackInfo().getTrack().getLonRange();
DoubleRange latRange = _app.getTrackInfo().getTrack().getLatRange();
final int minLon = (int) Math.floor(lonRange.getMinimum());
final int maxLon = (int) Math.floor(lonRange.getMaximum());
final int minLat = (int) Math.floor(latRange.getMinimum());
final int maxLat = (int) Math.floor(latRange.getMaximum());
for (int lon=minLon; lon<= maxLon; lon++)
{
for (int lat=minLat; lat <= maxLat; lat++)
{
SrtmTile tile = new SrtmTile(lat, lon);
boolean alreadyGot = false;
for (int t = 0; t < tileList.size(); t++)
{
if (tileList.get(t).equals(tile)) {
alreadyGot = true;
}
}
if (!alreadyGot) {tileList.add(tile);}
}
}
downloadTiles(tileList);
// Finished
_running = false;
}
/**
* Download the tiles of SRTM data
* @param inTileList list of tiles to get
*/
private void downloadTiles(ArrayList<SrtmTile> inTileList)
{
// Update progress bar
if (_progress != null)
{
_progress.setMaximum(inTileList.size());
_progress.setValue(0);
}
String errorMessage = null;
// Check the cache is ok
final String diskCachePath = Config.getConfigString(Config.KEY_DISK_CACHE);
if (diskCachePath != null)
{
File srtmDir = new File(diskCachePath, "srtm");
if (!srtmDir.exists() && !srtmDir.mkdir()) {
// can't create the srtm directory
errorMessage = I18nManager.getText("error.downloadsrtm.nocache");
}
}
else {
// no cache set up
errorMessage = I18nManager.getText("error.downloadsrtm.nocache");
}
// Get urls for each tile
URL[] urls = TileFinder.getUrls(inTileList);
int numDownloaded = 0;
for (int t=0; t<inTileList.size() && !_progress.isCancelled(); t++)
{
if (urls[t] != null)
{
// Define streams
FileOutputStream outStream = null;
InputStream inStream = null;
try
{
// Set progress
_progress.setValue(t);
// See if we've already got this tile or not
File outputFile = getFileToWrite(urls[t]);
if (outputFile != null)
{
// System.out.println("Download: Need to download: " + urls[t]);
outStream = new FileOutputStream(outputFile);
URLConnection conn = urls[t].openConnection();
conn.setRequestProperty("User-Agent", "GpsPrune v" + GpsPrune.VERSION_NUMBER);
inStream = conn.getInputStream();
// Copy all the bytes to the file
int c;
while ((c = inStream.read()) != -1)
{
outStream.write(c);
}
numDownloaded++;
}
// else System.out.println("Don't need to download: " + urls[t].getFile());
}
catch (IOException ioe) {errorMessage = ioe.getClass().getName() + " - " + ioe.getMessage();
}
// Make sure streams are closed
try {inStream.close();} catch (Exception e) {}
try {outStream.close();} catch (Exception e) {}
}
}
_progress.dispose();
if (_progress.isCancelled()) {
return;
}
if (errorMessage != null) {
_app.showErrorMessageNoLookup(getNameKey(), errorMessage);
}
else if (numDownloaded == 1)
{
JOptionPane.showMessageDialog(_parentFrame, I18nManager.getTextWithNumber("confirm.downloadsrtm.1", numDownloaded),
I18nManager.getText(getNameKey()), JOptionPane.INFORMATION_MESSAGE);
}
else if (numDownloaded > 1)
{
JOptionPane.showMessageDialog(_parentFrame, I18nManager.getTextWithNumber("confirm.downloadsrtm", numDownloaded),
I18nManager.getText(getNameKey()), JOptionPane.INFORMATION_MESSAGE);
}
else if (inTileList.size() > 0) {
_app.showErrorMessage(getNameKey(), "confirm.downloadsrtm.none");
}
}
/**
* See whether the SRTM file is already available locally
* @param inUrl URL for online resource
* @return file object to write to, or null if already there
*/
private static File getFileToWrite(URL inUrl)
{
String diskCachePath = Config.getConfigString(Config.KEY_DISK_CACHE);
if (diskCachePath != null)
{
File srtmDir = new File(diskCachePath, "srtm");
if (srtmDir.exists() && srtmDir.isDirectory() && srtmDir.canRead())
{
File srtmFile = new File(srtmDir, new File(inUrl.getFile()).getName());
if (!srtmFile.exists() || !srtmFile.canRead() || srtmFile.length() <= 400) {
return srtmFile;
}
}
}
return null;
}
/**
* @return true if a thread is currently running
*/
public boolean isRunning()
{
return _running;
}
}