/* ----------------------------------------
 * Origin  : GFI INFORMATIQUE 
 * Project : CDPP Propagation Tool 
 * ----------------------------------------
 * History 
 * Version : 25/08/2016 : SCA : V2.2.2
 * 	Creation
 * ----------------------------------------
 */
package fr.tlse.irap.pt.client.controller.tools.externalLinks;

import java.io.File;
import java.net.URL;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;

import org.apache.commons.io.FileUtils;

import eu.omp.irap.vespa.epntapclient.granule.Granule;
import fr.tlse.irap.pt.client.component.DialogComponent;
import fr.tlse.irap.pt.client.component.IDialogComponent;
import fr.tlse.irap.pt.client.controller.RootController;
import fr.tlse.irap.pt.client.controller.common.Formatter;
import fr.tlse.irap.pt.client.controller.dialogbox.DialogBox;
import fr.tlse.irap.pt.client.controller.tools.common.DesktopBrowser;
import fr.tlse.irap.pt.client.controller.tools.samp.JSampController;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.concurrent.Task;
import javafx.concurrent.Worker;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Cursor;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.MenuItem;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.stage.FileChooser;
import javafx.util.Callback;
/**
 * 
 * @author frup03304
 * @version
 */
public class ApisImagesComponent extends AnchorPane implements Initializable, IDialogComponent {

	DialogComponent dialog;
    List<Granule> granules = new ArrayList<Granule>();
    List<Image> icons = new ArrayList<Image>();
	final ContextMenu listMenu = new ContextMenu();

	@FXML protected ListView<String> listViewImages;
	@FXML protected ImageView iconView;
    
	@Override
	public void initialize(URL location, ResourceBundle resources) {

		loadMenu();

		listViewImages.setOnMouseClicked(new EventHandler<MouseEvent>() {
		    @Override
		    public void handle(MouseEvent click) {
	           int index = listViewImages.getSelectionModel().getSelectedIndex();
	           if (index >= 0 && index < granules.size()) {
	        	   if (click.getButton() == MouseButton.SECONDARY) {
	        		   listMenu.show(listViewImages, click.getScreenX(), click.getScreenY());
	        		   click.consume();
	        		   
	        	   } else {
			           String URL = granules.get(index).getAccessUrl();
			           if (granules.get(index).getProcessingLevel() == 3) {
					       // for raw fits format, get the .jpg image
			        	   URL = URL.replace(".fits", ".jpg");
			           }
			           try {
			        	   DesktopBrowser.open(URL);
			           } catch (Exception e) {
							DialogBox.error("Unable to open image URL in the current browser", dialog);
			           }
	        	   }
	           }
		    }
		});

		listViewImages.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
			@Override
			public ListCell<String> call(ListView<String> listView) {
				return new AttachmentListCell();
			}
		});

	}

	private class AttachmentListCell extends ListCell<String> {
		
		public AttachmentListCell() {
			setOnMouseMoved(new EventHandler<MouseEvent>() {
			    @Override
			    public void handle(MouseEvent move) {
			    	if (getIndex() >= 0 && getIndex() < icons.size()) {
			    		iconView.setImage(icons.get(getIndex()));
		       	        iconView.setFitHeight(35);
		       	        iconView.setFitWidth(35);
		       	        iconView.setY(getLayoutY());
		       	        iconView.setVisible(true);
		           }
			    }
			});
		}
		
		@Override
    	public void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);
            if (empty) {
                setGraphic(null);
                setText(null);
            } else {
            	Image fxImage = icons.get(getIndex());
       	        ImageView imageView = new ImageView(fxImage);
            	imageView.setFitHeight(16);
                imageView.setFitWidth(16);
                setGraphic(imageView);
                setText(item);
            }
        }
	}

	/**
	 * 
	 * @param granules
	 */
	public void initComponentWith(List<Granule> granules) {
		this.granules = granules;
		icons.clear();
		listViewImages.getItems().clear();
		List<String> items = new ArrayList<String>();
		for (Granule lGr : granules) {
			items.add(Formatter.getSdf().format(ExternalLinks.getDateFromJDN(lGr.getTimeMin())) + " - " + lGr.getGranuleGid() + " - " + lGr.getGranuleUid());
			icons.add(new Image(lGr.getThumbnailUrl(), true));
	    }
		listViewImages.getItems().addAll(FXCollections.observableArrayList(items));
		dialog.show();
	}

	@Override
	public void setDialog(DialogComponent dialog) {
		this.dialog = dialog;
	}

	/**
	 * Load context menu
	 */
	private void loadMenu() {
		final MenuItem saveAsItem = new MenuItem("Download");
		final MenuItem sendSAMPItem = new MenuItem("Send via SAMP");

		saveAsItem.setOnAction(new EventHandler<ActionEvent>() {
			@Override
			public void handle(ActionEvent event) {
				int index = listViewImages.getSelectionModel().getSelectedIndex();
				saveImage(granules.get(index).getAccessUrl(), 
						granules.get(index).getProcessingLevel());
			}
		});
		sendSAMPItem.setOnAction(new EventHandler<ActionEvent>() {
			@Override
			public void handle(ActionEvent event) {
				int index = listViewImages.getSelectionModel().getSelectedIndex();
		        if (granules.get(index).getProcessingLevel() != 5) {
		        	String URL = granules.get(index).getAccessUrl();
			        if (granules.get(index).getProcessingLevel() == 4) {
				       // for proc pdf format, get the .fits image
		        	   URL = URL.replace(".pdf", ".fits");
			        }
					sendToSamp(URL);
		        }
			}
		});
		listMenu.getItems().add(saveAsItem);
		listMenu.getItems().add(sendSAMPItem);
	}

	/**
	 * Download image URL  
	 */
	private void saveImage(final String url, int procLevel) {
		// Download image
		FileChooser fileChooser = new FileChooser();

		//Set initial dir
		String currentDir = System.getProperty("user.home") + File.separator;
		fileChooser.setInitialDirectory(new File(currentDir));
        
		//Set extension filter
		FileChooser.ExtensionFilter pdf = new FileChooser.ExtensionFilter("PDF files (*.pdf)", "*.pdf");
		FileChooser.ExtensionFilter jpg = new FileChooser.ExtensionFilter("JPG files (*.jpg)", "*.jpg");
		FileChooser.ExtensionFilter fits = new FileChooser.ExtensionFilter("FITS files (*.fits)", "*.fits");
		if (procLevel == 3) { // Raw data
            fileChooser.getExtensionFilters().add(fits);
            fileChooser.getExtensionFilters().add(jpg);
		}
		else if (procLevel == 4) { // Processed
            fileChooser.getExtensionFilters().add(pdf);
            fileChooser.getExtensionFilters().add(fits);
            fileChooser.getExtensionFilters().add(jpg);
		}
		else { // Projections
            fileChooser.getExtensionFilters().add(pdf);
            fileChooser.getExtensionFilters().add(jpg);
		}

		waitCursor();
		//final WaitProcess waitProcess = new WaitProcess(this);
        final File file = fileChooser.showSaveDialog(RootController.stage);
        if (file != null){

			Platform.runLater(new Runnable() {
				@Override public void run() {
		            //Show save file dialog
	            	String newUrl = url;
	            	String suffix = file.getName().substring(file.getName().lastIndexOf("."));
	            	String suffixUrl = url.substring(url.lastIndexOf("."));
	            	if (!suffix.equals(suffixUrl)) {
	            		newUrl = url.replace(suffixUrl, suffix);
	            	}
	            	try {
	            		FileUtils.copyURLToFile(new URL(newUrl), file);
	            	}
	            	catch (Exception e) {
	            		e.printStackTrace();
	        			DialogBox.error(" Error while downloading URL file.\n");
	            	}
	        		endCursor();
	        		//waitProcess.stop();
	        	}
			});
        }
        else {
        	endCursor();
        	//waitProcess.stop();
        }
	}

	/**
	 * Send XML VoTable file to SAMP  
	 * @param xmlFile
	 */
	private void sendToSamp(final String url) {
		final Task<Object> sendToSampWorker = sendToSampWorker(url);

		sendToSampWorker.stateProperty().addListener(
				new ChangeListener<Worker.State>() {
					@Override
					public void changed(ObservableValue<? extends Worker.State> observableValue, Worker.State oldState, Worker.State newState) {
						if (newState == Worker.State.SUCCEEDED) {
							endCursor();
						} else if (newState == Worker.State.FAILED || newState == Worker.State.CANCELLED) {
							endCursor();
							DialogBox.error(" Error while exporting image fits to SAMP.\n");
							if (sendToSampWorker.getException() != null) {
								System.out.println(sendToSampWorker.getException().getMessage());
							}
						}
					}
				});
		new Thread(sendToSampWorker).start();
		waitCursor();
	}

	private Task<Object> sendToSampWorker(final String url) {
		return new Task<Object>() {
			@Override
			protected Object call() throws Exception {
				// Export via SAMP hub
				File fitsFile = File.createTempFile("apisImage", ".fits");
				FileUtils.copyURLToFile(new URL(url), fitsFile);
				String path = "file:///" + Paths.get(fitsFile.getPath());
				path = path.replaceAll("\\\\", "/");
				JSampController.getJSampFrame().sendFits(path);
				return true;
			}
		};
	}

	private void waitCursor() {
		this.setDisable(true);
		this.getScene().setCursor(Cursor.WAIT);
	}

	private void endCursor() {
		this.setDisable(false);
		this.getScene().setCursor(null);
	}

}