content: package tim.prune.load;
  
  import java.io.File;
  import java.util.ArrayList;
  
  import javax.swing.JFileChooser;
  
  import tim.prune.App;
  import tim.prune.I18nManager;
  import tim.prune.cmd.Command;
  import tim.prune.cmd.LoadPhotosWithPointsCmd;
  import tim.prune.config.Config;
  import tim.prune.data.Photo;
  import tim.prune.load.json.JsonFileLoader;
  import tim.prune.load.xml.GzipFileLoader;
  import tim.prune.load.xml.XmlFileLoader;
  import tim.prune.load.xml.ZipFileLoader;
  
  
  /**
   * Generic FileLoader class to select a file
   * and pass handling on to appropriate loader
   */
  public class FileLoader
  {
  	private final App _app;
  	private JFileChooser _fileChooser = null;
  	private final TextFileLoader _textFileLoader;
  	private final NmeaFileLoader _nmeaFileLoader;
  	private final XmlFileLoader _xmlFileLoader;
  	private final ZipFileLoader _zipFileLoader;
  	private final GzipFileLoader _gzipFileLoader;
  
  
  	/**
  	 * Constructor
  	 * @param inApp Application object to inform of track load
  	 */
  	public FileLoader(App inApp)
  	{
  		_app = inApp;
  		_textFileLoader = new TextFileLoader(inApp);
  		_nmeaFileLoader = new NmeaFileLoader(inApp);
  		_xmlFileLoader = new XmlFileLoader(inApp);
  		_zipFileLoader = new ZipFileLoader(inApp, _xmlFileLoader);
  		_gzipFileLoader = new GzipFileLoader(inApp, _xmlFileLoader);
  	}
  
  
  	/**
  	 * Select an input file and open the GUI frame
  	 * to select load options
  	 */
  	public void openFile()
  	{
  		// Construct file chooser if necessary
  		if (_fileChooser == null)
  		{
  			_fileChooser = new JFileChooser();
  			_fileChooser.addChoosableFileFilter(new GenericFileFilter("filetypefilter.txt", new String[] {"txt", "text"}));
  			_fileChooser.addChoosableFileFilter(new GenericFileFilter("filetypefilter.gpx", new String[] {"gpx"}));
  			_fileChooser.addChoosableFileFilter(new GenericFileFilter("filetypefilter.kml", new String[] {"kml"}));
  			_fileChooser.addChoosableFileFilter(new GenericFileFilter("filetypefilter.kmz", new String[] {"kmz"}));
  			_fileChooser.setAcceptAllFileFilterUsed(true);
  			_fileChooser.setFileFilter(_fileChooser.getAcceptAllFileFilter()); // For some reason seems necessary
  			// start from directory in config if already set (by load jpegs)
  			Config config = _app.getConfig();
  			String configDir = config.getConfigString(Config.KEY_TRACK_DIR);
  			if (configDir == null) {configDir = config.getConfigString(Config.KEY_PHOTO_DIR);}
  			if (configDir != null) {
  				_fileChooser.setCurrentDirectory(new File(configDir));
  			}
  			_fileChooser.setMultiSelectionEnabled(true); // Allow multiple selections
  		}
  		// Show the open dialog
  		if (_fileChooser.showOpenDialog(_app.getFrame()) == JFileChooser.APPROVE_OPTION)
  		{
  			File[] files = _fileChooser.getSelectedFiles();
  			// Loop through files looking for files which exist and are readable
  			ArrayList<File> dataFiles = new ArrayList<>();
  			if (files != null)
  			{
  				for (File file : files)
  				{
  					if (file.exists() && file.isFile() && file.canRead()) {
  						dataFiles.add(file);
  					}
  				}
  			}
  			if (dataFiles.size() > 0) {
  				_app.loadDataFiles(dataFiles);
  			}
  			else
  			{
  				// couldn't find any files to load - show error message
  				_app.showErrorMessage("error.load.dialogtitle", "error.load.noread");
  			}
  		}
  	}
  
  	/**
  	 * Open the selected input file
  	 * @param inFile file to open
  	 * @param inAutoAppend true to automatically append without asking
  	 */
  	public void openFile(File inFile, boolean inAutoAppend)
  	{
  		// Store directory in config for later
  		File parentDir = inFile.getParentFile();
  		if (parentDir != null) {
  			_app.getConfig().setConfigString(Config.KEY_TRACK_DIR, parentDir.getAbsolutePath());
  		}
  		FileToBeLoaded fileLock = new FileToBeLoaded(inFile, _app::informDataLoadComplete);
  		// Check file type to see if it's xml or just normal text
  		String fileExtension = inFile.getName().toLowerCase();
  		if (fileExtension.length() > 4) {
  			fileExtension = fileExtension.substring(fileExtension.length() - 4);
  		}
  		if (fileExtension.equals(".kml") || fileExtension.equals(".gpx")
  			|| fileExtension.equals(".xml"))
  		{
  			// Use xml loader for kml, gpx and xml filenames
  			_xmlFileLoader.openFile(fileLock, inAutoAppend);
  		}
  		else if (fileExtension.equals(".kmz") || fileExtension.equals(".zip"))
  		{
  			// Use zip loader for zipped kml (or zipped gpx)
  			_zipFileLoader.openFile(fileLock, inAutoAppend);
  		}
  		else if (fileExtension.endsWith(".gz") || fileExtension.equals("gzip"))
  		{
  			// Use gzip loader for gzipped xml
  			_gzipFileLoader.openFile(fileLock, inAutoAppend);
  		}
  		else if (fileExtension.equals("nmea"))
  		{
  			_nmeaFileLoader.openFile(fileLock, inAutoAppend);
  		}
  		else if (fileExtension.equals(".jpg") || fileExtension.equals("jpeg"))
  		{
  			Photo photo = JpegLoader.createPhoto(inFile);
  			Command command = new LoadPhotosWithPointsCmd(photo);
  			command.setDescription(I18nManager.getText("undo.loadphoto", inFile.getName()));
  			command.setConfirmText(I18nManager.getText("confirm.jpegload.single"));
  			_app.execute(command);
  		}
  		else if (fileExtension.equals("json"))
  		{
  			new JsonFileLoader(_app).openFile(fileLock, inAutoAppend);
  		}
  		else
  		{
  			// Use text loader for everything else
  			_textFileLoader.openFile(fileLock, inAutoAppend);
  		}
  		// Release our lock, maybe the file type loader has its own now
  		fileLock.release();
  	}
  
  	/**
  	 * @return the last delimiter character used for a text file load
  	 */
  	public char getLastUsedDelimiter() {
  		return _textFileLoader.getLastUsedDelimiter();
  	}
  }
  