package org.gcube.portlets.user.speciesdiscovery.client.job.occurrence;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import org.gcube.portlets.user.speciesdiscovery.client.ConstantsSpeciesDiscovery;
import org.gcube.portlets.user.speciesdiscovery.client.SpeciesDiscovery;
import org.gcube.portlets.user.speciesdiscovery.client.event.ReLoadListJobEvent;
import org.gcube.portlets.user.speciesdiscovery.client.event.ReSubmitJobEvent;
import org.gcube.portlets.user.speciesdiscovery.client.event.SaveJobErrorEvent;
import org.gcube.portlets.user.speciesdiscovery.client.event.SaveJobEvent;
import org.gcube.portlets.user.speciesdiscovery.client.resources.Resources;
import org.gcube.portlets.user.speciesdiscovery.client.window.MessageBoxConfirm;
import org.gcube.portlets.user.speciesdiscovery.shared.DataSource;
import org.gcube.portlets.user.speciesdiscovery.shared.DownloadState;
import org.gcube.portlets.user.speciesdiscovery.shared.JobOccurrencesModel;
import org.gcube.portlets.user.speciesdiscovery.shared.JobTaxonomyModel;
import org.gcube.portlets.user.speciesdiscovery.shared.SearchResultType;

import com.allen_sauer.gwt.log.client.Log;
import com.extjs.gxt.ui.client.Style.ButtonScale;
import com.extjs.gxt.ui.client.Style.SelectionMode;
import com.extjs.gxt.ui.client.data.BaseModelData;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.event.BaseEvent;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.GridEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.MenuEvent;
import com.extjs.gxt.ui.client.event.MessageBoxEvent;
import com.extjs.gxt.ui.client.event.SelectionChangedEvent;
import com.extjs.gxt.ui.client.event.SelectionChangedListener;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.Dialog;
import com.extjs.gxt.ui.client.widget.Info;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnData;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer;
import com.extjs.gxt.ui.client.widget.grid.filters.DateFilter;
import com.extjs.gxt.ui.client.widget.grid.filters.GridFilters;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.menu.Menu;
import com.extjs.gxt.ui.client.widget.menu.MenuItem;
import com.extjs.gxt.ui.client.widget.toolbar.FillToolItem;
import com.extjs.gxt.ui.client.widget.toolbar.SeparatorToolItem;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbstractImagePrototype;

/**
 *
 * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it
 *
 */
public class OccurrenceGridJob extends ContentPanel{


	private static final String REFRESH_LIST = "Refresh List";
	private static final String RE_SUBMIT = "Re-submit";
	private static final String SAVE = "Save";
	private static final String SAVEERROR = "Save Errors";
	private static final String CANCEL = "Cancel";
	private static final String INFO = "Info";
	//	public static final String DATE_TIME_FORMAT = "yyyy.MM.dd 'at' HH:mm:ss";
	//	private ListStore<FileModel> store =  ListStoreModel.getInstance().getStore();
	private ListStore<BaseModelData> store;
	private ToolBar toolBar = new ToolBar();
	private Grid<BaseModelData> grid;
	private HashMap<String,OccurrenceWindowInfoJobsSpecies> listWindowInfo = new HashMap<String, OccurrenceWindowInfoJobsSpecies>();
	private EventBus eventBus;

	private Button buttonInfo;
	private Button buttonCancel;
	private Button buttonSave;
	private Button buttonSaveError;
	private Button buttonReSubmit;
	private Button buttonRefreshList;
	private Menu menu = new Menu();

	public OccurrenceGridJob(EventBus eventBus) {

		this.eventBus = eventBus;

		ColumnConfig name = new ColumnConfig(JobOccurrencesModel.JOBNAME, JobOccurrencesModel.JOBNAME, 220);
		ColumnConfig dataSources = new ColumnConfig(JobOccurrencesModel.DATASOURCESASSTRING, JobOccurrencesModel.DATASOURCESASSTRING, 140);
		ColumnConfig progress = new ColumnConfig(JobOccurrencesModel.PROGRESS, JobOccurrencesModel.PROGRESS, 150);

		ColumnConfig startDate = new ColumnConfig(JobOccurrencesModel.STARTTIME, JobOccurrencesModel.STARTTIME, 140);

		ColumnConfig submitDate = new ColumnConfig(JobOccurrencesModel.SUBMITTIME, JobOccurrencesModel.SUBMITTIME, 140);
//		creationDate.setDateTimeFormat(DateTimeFormat.getFormat(DATE_TIME_FORMAT));

		ColumnConfig endTime = new ColumnConfig(JobOccurrencesModel.ENDTIME, JobOccurrencesModel.ENDTIME, 140);
//		endTime.setDateTimeFormat(DateTimeFormat.getFormat(DATE_TIME_FORMAT));

		ColumnConfig elapsedTime = new ColumnConfig(JobOccurrencesModel.ELAPSEDTIME, JobOccurrencesModel.ELAPSEDTIME + " Days, " + ConstantsSpeciesDiscovery.TIMEFORMAT_HH_MM_SS, 100);
//		elapsedTime.setHidden(true);

		ColumnConfig fileFormat = new ColumnConfig(JobOccurrencesModel.FILEFORMAT, JobOccurrencesModel.FILEFORMAT, 100);

		ColumnConfig csvType = new ColumnConfig(JobOccurrencesModel.CSVTYPE, JobOccurrencesModel.CSVTYPE, 100);

		ColumnConfig status = new ColumnConfig(JobOccurrencesModel.STATUS, JobOccurrencesModel.STATUS, 80);

		ColumnConfig itemsCount = new ColumnConfig(JobOccurrencesModel.ITEMSNUMBER, JobOccurrencesModel.ITEMSNUMBER, 95);

		final ColumnModel cm = new ColumnModel(Arrays.asList(name, dataSources, itemsCount, progress, submitDate, startDate, endTime, elapsedTime, fileFormat, csvType, status));

		setBodyBorder(false);
		setHeaderVisible(false);
		setLayout(new FitLayout());

		GridFilters filters = new GridFilters();
		filters.setLocal(true);

		DateFilter dateFilterStartDate = new DateFilter(JobOccurrencesModel.STARTTIME);
		DateFilter dateFilterSubmitDate = new DateFilter(JobOccurrencesModel.SUBMITTIME);
		DateFilter dateFilterEnd = new DateFilter(JobOccurrencesModel.ENDTIME);

		filters.addFilter(dateFilterStartDate);
		filters.addFilter(dateFilterSubmitDate);
		filters.addFilter(dateFilterEnd);

		store = new ListStore<BaseModelData>();

		grid = new Grid<BaseModelData>(store, cm);
		grid.setLoadMask(true);

	    GridCellRenderer<BaseModelData> downloadStateRenderer = new GridCellRenderer<BaseModelData>() {
			@Override
			public String render(BaseModelData model, String property, ColumnData config, int rowIndex, int colIndex, ListStore<BaseModelData> store, Grid<BaseModelData> grid) {
		          String val = model.get(property).toString();
		          String color="black";

//		          ONGOING, ONGOINGWITHFAILURES, FAILED, COMPLETED, COMPLETEDWITHFAILURES

		          if(val!=null){
	        		  if(val.compareTo(DownloadState.SAVING.toString())==0){
	        			  color = "#7093DB";
			          }else if(val.compareTo(DownloadState.FAILED.toString())==0){
			        	  color = "#f00";
			          }
		          }
		          else
		        	  val = "";

		          return "<span qtitle='" + cm.getColumnById(property).getHeader() + "' qtip='" + val  + "' style='color:" + color + "'>" + val + "</span>";

			}
	      };

	      GridCellRenderer<BaseModelData> jobSpeciesRenderer = new GridCellRenderer<BaseModelData>() {

	          public Object render(final BaseModelData model, String property, ColumnData config, final int rowIndex,
	              final int colIndex, ListStore<BaseModelData> store, Grid<BaseModelData> grid) {

	              grid.addListener(Events.ColumnResize, new Listener<GridEvent<BaseModelData>>() {

	                public void handleEvent(GridEvent<BaseModelData> be) {

	                  for (int i = 0; i < be.getGrid().getStore().getCount(); i++) {
	                    if (be.getGrid().getView().getWidget(i, be.getColIndex()) != null
	                        && be.getGrid().getView().getWidget(i, be.getColIndex()) instanceof OccurrenceJobSpeciesProgressBar) {
	                      ((OccurrenceJobSpeciesProgressBar) be.getGrid().getView().getWidget(i, be.getColIndex())).setWidth(be.getWidth() - 10);
	                    }
	                  }
	                }
	              });

	            return model.get(property);
	          }
	        };

	    progress.setRenderer(jobSpeciesRenderer);
	    status.setRenderer(downloadStateRenderer);


//		grid.getView().setAutoFill(true);

		grid.getView().setEmptyText("Empty");

		grid.getView().setShowDirtyCells(false);
		grid.getView().setShowInvalidCells(false);

//		setAlphanumericStoreSorter(grid);

//		grid.setAutoExpandColumn(JobOccurrencesModel.JOBNAME);
		grid.setBorders(false);
//		grid.setStripeRows(true);
		grid.setColumnLines(true);
		grid.addPlugin(filters);

		grid.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);

		grid.getSelectionModel().addSelectionChangedListener(new SelectionChangedListener<BaseModelData>() {

			@Override
			public void selectionChanged(SelectionChangedEvent<BaseModelData> se) {
//				System.out.println("selection grid change");

				ModelData target = se.getSelectedItem();

				if(target!=null)
					enableButtonOnClick(true);
				else
					enableButtonOnClick(false);

			}
		});

		add(grid);

		createGridToolBar();
		createMenuItemsOnGrid();
	}

	public void addJobIntoGrid(JobOccurrencesModel jobModel, OccurrenceJobSpeciesProgressBar jobProgressBar) {

		BaseModelData baseModelData = new BaseModelData();

		baseModelData.set(JobOccurrencesModel.JOBINDENTIFIER, jobModel.getJobIdentifier());
		baseModelData.set(JobOccurrencesModel.JOBNAME, jobModel.getJobName());
		baseModelData.set(JobOccurrencesModel.PROGRESS, jobProgressBar);
		baseModelData.set(JobOccurrencesModel.STATUS, jobModel.getDownloadState().toString());

		baseModelData.set(JobOccurrencesModel.SUBMITTIME, jobModel.getSubmitTime());
		baseModelData.set(JobOccurrencesModel.ENDTIME, jobModel.getEndTime());

		baseModelData.set(JobOccurrencesModel.FILEFORMAT, jobModel.getFileFormat());
		baseModelData.set(JobOccurrencesModel.CSVTYPE, jobModel.getCsvType());

		baseModelData.set(JobOccurrencesModel.STARTTIME, jobModel.getStartTime());

		baseModelData.set(JobOccurrencesModel.ELAPSEDTIME, jobModel.getElapsedTime());

		baseModelData.set(JobOccurrencesModel.COMPLETEDENTRY, jobModel.getNodeCompleted());

		baseModelData.set(JobOccurrencesModel.ITEMSNUMBER, jobModel.getTotalOccurrences());

		String dataSources = "";
		for (DataSource dataSource : jobModel.getDataSources()) {
			dataSources+= " "+dataSource.getName() + ",";
		}

		//Trim
		dataSources = dataSources.trim();

		//Remove last char ,
		dataSources = dataSources.substring(0, dataSources.lastIndexOf(","));

		baseModelData.set(JobOccurrencesModel.DATASOURCESASSTRING, dataSources);
		baseModelData.set(JobOccurrencesModel.SCIENTIFICNAME, jobModel.getScientificName());

		baseModelData.set(JobOccurrencesModel.DESCRIPTION, jobModel.getDescription());

		baseModelData.set(jobModel.getJobIdentifier(), jobModel); //store object JobOccurrencesModel

		store.add(baseModelData);
		updateJobInfo(jobModel);
	}

	private void updateJobInfo(JobOccurrencesModel jobModel){

		OccurrenceWindowInfoJobsSpecies win=listWindowInfo.get(jobModel.getJobIdentifier());

		if(win==null){
			win = new OccurrenceWindowInfoJobsSpecies();
			win.setWindowTitle("Job " + jobModel.getJobName() + " description:");
		}

		win.updateDescription(jobModel);

		listWindowInfo.put(jobModel.getJobIdentifier(), win);
	}

	public void updateStatus(JobOccurrencesModel jobModel, OccurrenceJobSpeciesProgressBar jobProgressBar){

		BaseModelData job  = store.findModel(JobOccurrencesModel.JOBINDENTIFIER, jobModel.getJobIdentifier());

		if(job!=null){

			job.set(JobOccurrencesModel.PROGRESS, jobProgressBar);
			job.set(JobOccurrencesModel.SUBMITTIME, jobModel.getSubmitTime());
			job.set(JobOccurrencesModel.STATUS, jobModel.getDownloadState().toString());
			job.set(JobOccurrencesModel.ENDTIME, jobModel.getEndTime());
			job.set(JobOccurrencesModel.ELAPSEDTIME, jobModel.getElapsedTime());
			job.set(JobOccurrencesModel.STARTTIME, jobModel.getStartTime());

			updateJobInfo(jobModel);

			store.update(job);
		}

	}


	public void removeSpeciesJobByIdentifier(String jobIdentifier) {
		BaseModelData job = store.findModel(JobOccurrencesModel.JOBINDENTIFIER, jobIdentifier);
		if(job!=null){
			store.remove(job);
		}
	}

	private void viewInfoJob() {

		BaseModelData baseModelData = grid.getSelectionModel().getSelectedItem();

		if(baseModelData!=null){

			OccurrenceWindowInfoJobsSpecies win = listWindowInfo.get(baseModelData.get(JobOccurrencesModel.JOBINDENTIFIER));
			win.show();
		}
	}

	private void cancelJob() {

		final BaseModelData baseModelData = grid.getSelectionModel().getSelectedItem();

		if(baseModelData!=null){

			String name = baseModelData.get(JobOccurrencesModel.JOBNAME);

				MessageBoxConfirm mbc = new MessageBoxConfirm(ConstantsSpeciesDiscovery.CONFIRM_DELETE, ConstantsSpeciesDiscovery.MESSAGE_CONFIRM_DELETE_JOB  + " "+ name+"?");
				mbc.getMessageBoxConfirm().addCallback(new Listener<MessageBoxEvent>() {

				public void handleEvent(MessageBoxEvent be) {

					//IF CANCELLED
					String clickedButton = be.getButtonClicked().getItemId();
					if(clickedButton.equals(Dialog.YES)){

						final String jobIdentifier = baseModelData.get(JobOccurrencesModel.JOBINDENTIFIER);

						SpeciesDiscovery.taxonomySearchService.cancelOccurrenceJob(jobIdentifier, new AsyncCallback<Boolean>() {

							@Override
							public void onSuccess(Boolean result) {

								if(result)
									removeSpeciesJobByIdentifier(jobIdentifier);

							}

							@Override
							public void onFailure(Throwable caught) {
								Info.display("Error", "An error occurred during the cancel");
								Log.error("Error during the cancel", caught.getMessage());

							}
						});

					}
				}
			});

		}

	}

	private void saveJob() {
		BaseModelData baseModelData = grid.getSelectionModel().getSelectedItem();

		if(baseModelData!=null){

			String load = baseModelData.get(JobOccurrencesModel.STATUS).toString();

			if(load.compareTo(DownloadState.COMPLETED.toString())==0 || load.compareTo(DownloadState.SAVED.toString())==0 ){

				String jobIdentifier = baseModelData.get(JobOccurrencesModel.JOBINDENTIFIER);
				String scientificName = baseModelData.get(JobOccurrencesModel.SCIENTIFICNAME);

				JobOccurrencesModel jobModel = baseModelData.get(jobIdentifier);

				List<DataSource> dataSourceList = jobModel.getDataSources();

				eventBus.fireEvent(new SaveJobEvent(jobIdentifier, scientificName, dataSourceList, SearchResultType.OCCURRENCE_POINT, jobModel));
			}

			else{
				String name = baseModelData.get(JobOccurrencesModel.JOBNAME);
				MessageBox.alert(ConstantsSpeciesDiscovery.ALERT, "The job "+ name+ " " +ConstantsSpeciesDiscovery.IS_NOT_COMPLETED, null);
			}
		}

	}

	private void saveErrorJob() {

		BaseModelData baseModelData = grid.getSelectionModel().getSelectedItem();

		if(baseModelData!=null){

			String load = baseModelData.get(JobOccurrencesModel.STATUS).toString();

			if(load.compareTo(DownloadState.COMPLETED.toString())==0 || load.compareTo(DownloadState.SAVED.toString())==0 || load.compareTo(DownloadState.FAILED.toString())==0){

				String jobIdentifier = baseModelData.get(JobOccurrencesModel.JOBINDENTIFIER);
				String scientificName = baseModelData.get(JobOccurrencesModel.SCIENTIFICNAME);

				JobOccurrencesModel jobModel = baseModelData.get(jobIdentifier);

				List<DataSource> dataSourceList = jobModel.getDataSources();

				eventBus.fireEvent(new SaveJobErrorEvent(jobIdentifier, scientificName, dataSourceList, SearchResultType.OCCURRENCE_POINT, jobModel));
			}

			else{
				String name = baseModelData.get(JobOccurrencesModel.JOBNAME);
				MessageBox.alert(ConstantsSpeciesDiscovery.ALERT, "The error file "+ name+ " " +ConstantsSpeciesDiscovery.IS_NOT_COMPLETED, null);
			}
		}

	}


	private void resubmitJob() {

		BaseModelData baseModelData = grid.getSelectionModel().getSelectedItem();

		if(baseModelData!=null){

			String load = baseModelData.get(JobTaxonomyModel.STATUS).toString();

			if(load.compareTo(DownloadState.FAILED.toString())==0 || load.compareTo(DownloadState.COMPLETED.toString())==0 || load.compareTo(DownloadState.SAVED.toString())==0 ){

				String jobIdentifier = baseModelData.get(JobOccurrencesModel.JOBINDENTIFIER);

				JobOccurrencesModel jobModel = (JobOccurrencesModel) baseModelData.get(jobIdentifier); //get object JobOccurrencesModel

				eventBus.fireEvent(new ReSubmitJobEvent(SearchResultType.OCCURRENCE_POINT, jobModel, null, null));
			}

			else{
				String name = baseModelData.get(JobTaxonomyModel.JOBNAME);
				MessageBox.alert(INFO, "The job "+ name+ " " + ConstantsSpeciesDiscovery.CAN_NOT_BE_RE_SUBMITTED_UNTIL_IT_HAS_COMPLETED, null);
			}
		}

	}

	private void createGridToolBar(){

		buttonInfo = new Button(INFO);
		buttonInfo.setScale(ButtonScale.MEDIUM);
		buttonInfo.setIcon(AbstractImagePrototype.create(Resources.INSTANCE.getInfoIcon()));
		buttonInfo.setStyleAttribute("margin-left", "5px");
		buttonInfo.addSelectionListener(new SelectionListener<ButtonEvent>() {

			@Override
			public void componentSelected(ButtonEvent ce) {
				viewInfoJob();
			}
		});

		buttonCancel =  new Button(CANCEL);
		buttonCancel.setScale(ButtonScale.MEDIUM);
		buttonCancel.setIcon(AbstractImagePrototype.create(Resources.INSTANCE.getDelete()));

		buttonCancel.addListener(Events.OnClick, new Listener<BaseEvent>() {

			@Override
			public void handleEvent(BaseEvent be) {

				cancelJob();
			}

		});

		buttonSave =  new Button(SAVE);
		buttonSave.setIcon(AbstractImagePrototype.create(Resources.INSTANCE.getSaveProducts()));
		buttonSave.setScale(ButtonScale.MEDIUM);
		buttonSave.addListener(Events.OnClick, new Listener<BaseEvent>() {

			@Override
			public void handleEvent(BaseEvent be) {

				saveJob();
			}
		});


		buttonSaveError =  new Button(SAVEERROR);
		buttonSaveError.setIcon(AbstractImagePrototype.create(Resources.INSTANCE.getSaveProducts()));
		buttonSaveError.setScale(ButtonScale.MEDIUM);
		buttonSaveError.addListener(Events.OnClick, new Listener<BaseEvent>() {

			@Override
			public void handleEvent(BaseEvent be) {

				saveErrorJob();
			}

		});

		buttonReSubmit =  new Button(RE_SUBMIT);
		buttonReSubmit.setIcon(AbstractImagePrototype.create(Resources.INSTANCE.getReSubmit()));
		buttonReSubmit.setScale(ButtonScale.MEDIUM);
		buttonReSubmit.addListener(Events.OnClick, new Listener<BaseEvent>() {

			@Override
			public void handleEvent(BaseEvent be) {

				resubmitJob();
			}

		});


		buttonRefreshList =  new Button(REFRESH_LIST);
		buttonRefreshList.setIcon(AbstractImagePrototype.create(Resources.INSTANCE.getRefresh()));
		buttonRefreshList.setScale(ButtonScale.MEDIUM);
		buttonRefreshList.addListener(Events.OnClick, new Listener<BaseEvent>() {

			@Override
			public void handleEvent(BaseEvent be) {

//				resetStore();
				eventBus.fireEvent(new ReLoadListJobEvent(SearchResultType.OCCURRENCE_POINT));

			}
		});



		toolBar.add(buttonInfo);
		toolBar.add(new SeparatorToolItem());

		toolBar.add(buttonSave);
		toolBar.add(new SeparatorToolItem());

		toolBar.add(buttonSaveError);
		toolBar.add(new SeparatorToolItem());

		toolBar.add(buttonCancel);
		toolBar.add(new SeparatorToolItem());

		toolBar.add(buttonReSubmit);
		toolBar.add(new SeparatorToolItem());

		toolBar.add(new FillToolItem());
		toolBar.add(new SeparatorToolItem());
		toolBar.add(buttonRefreshList);

		setTopComponent(toolBar);

		enableButtonOnClick(false);
	}

	public void enableToolBar(boolean bool){
		this.toolBar.setEnabled(bool);
	}

	public void resetStore(){
		store.removeAll();
	}

	public void enableButtonOnClick(boolean bool){
		this.buttonCancel.setEnabled(bool);
		this.buttonInfo.setEnabled(bool);
		this.buttonSave.setEnabled(bool);
		this.buttonReSubmit.setEnabled(bool);
		this.buttonSaveError.setEnabled(bool);
	}

	public void createMenuItemsOnGrid(){

		MenuItem menuInfo = new MenuItem();
		menuInfo.setText(INFO);
		menuInfo.setIcon(AbstractImagePrototype.create(Resources.INSTANCE.getInfoIcon()));

		menuInfo.addSelectionListener(new SelectionListener<MenuEvent>() {

			@Override
			public void componentSelected(MenuEvent ce) {
				viewInfoJob();
			}

		});

		menu.add(menuInfo);

		MenuItem menuSave= new MenuItem();
		menuSave.setText(SAVE);
		menuSave.setIcon(AbstractImagePrototype.create(Resources.INSTANCE.getSaveProducts()));

		menuSave.addSelectionListener(new SelectionListener<MenuEvent>() {

			@Override
			public void componentSelected(MenuEvent ce) {
				saveJob();
			}

		});

		menu.add(menuSave);

		MenuItem menuSaveError = new MenuItem();
		menuSaveError.setText(SAVEERROR);
		menuSaveError.setIcon(AbstractImagePrototype.create(Resources.INSTANCE.getSaveProducts()));

		menuSaveError.addSelectionListener(new SelectionListener<MenuEvent>() {

			@Override
			public void componentSelected(MenuEvent ce) {
				saveErrorJob();
			}

		});

		menu.add(menuSaveError);


		MenuItem menuCancel= new MenuItem();
		menuCancel.setText(CANCEL);
		menuCancel.setIcon(AbstractImagePrototype.create(Resources.INSTANCE.getDelete()));

		menuCancel.addSelectionListener(new SelectionListener<MenuEvent>() {

			@Override
			public void componentSelected(MenuEvent ce) {

				cancelJob();
			}

		});

		menu.add(menuCancel);

		MenuItem menuResubmit= new MenuItem();
		menuResubmit.setText(RE_SUBMIT);
		menuResubmit.setIcon(AbstractImagePrototype.create(Resources.INSTANCE.getReSubmit()));

		menuResubmit.addSelectionListener(new SelectionListener<MenuEvent>() {

			@Override
			public void componentSelected(MenuEvent ce) {
				resubmitJob();
			}

		});

		menu.add(menuResubmit);

		grid.setContextMenu(menu);

	}

}
