package org.gcube.portlets.user.reportgenerator.client.targets;

import java.util.LinkedList;
import java.util.List;

import org.gcube.portlets.d4sreporting.common.shared.TimeSeriesFilter;
import org.gcube.portlets.d4sreporting.common.shared.TimeSeriesinfo;
import org.gcube.portlets.d4sreporting.common.shared.Table;
import org.gcube.portlets.d4sreporting.common.shared.RepTimeSeries;
import org.gcube.portlets.user.reportgenerator.client.ReportGenerator;
import org.gcube.portlets.user.reportgenerator.client.Presenter.Presenter;
import org.gcube.portlets.user.reportgenerator.client.dialog.TimeSeriesDialog;
import org.gcube.portlets.user.reportgenerator.client.dialog.TimeSeriesFilterDialog;
import org.gcube.portlets.user.reportgenerator.client.dialog.TimeSeriesSampleDialog;
import org.gcube.portlets.user.workspace.client.workspace.GWTWorkspaceItem;
import org.gcube.portlets.user.workspace.client.workspace.folder.item.GWTTimeSeries;

import com.extjs.gxt.ui.client.widget.Composite;
import com.extjs.gxt.ui.client.widget.VerticalPanel;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;



/**
 * <code> TSArea </code> class is a Widget you can drop a Workspace Time Series on
 *
 * @author Massimiliano Assante, ISTI-CNR - massimiliano.assante@isti.cnr.it
 * @version July 2011 (3.0) 
 */
public class TSArea extends Composite {

	private VerticalPanel mainPanel;	
	private RepTimeSeries sts = new RepTimeSeries();
	private String idInBasket;
	private Presenter presenter;
	private FlexTable flexTable;
	private TSArea singleton;

	VerticalPanel tableContainer = new VerticalPanel();
	Grid metadata = new Grid(3, 2);
	
	Label label;
	/**
	 * @param presenter .
	 * @param width  .
	 * @param height . 
	 * @param sts the time series
	 */
	public TSArea(Presenter presenter, int width, int height, RepTimeSeries sts) {
		singleton = this;
		this.presenter = presenter;
		mainPanel = new VerticalPanel();
		//setElement(mainPanel.getElement());
	
		mainPanel.setStyleName("timeseriesArea");
		mainPanel.addStyleName("timeseriesArea_bg");
		mainPanel.setWidth(width);
		mainPanel.setHeight(height);
		
		mainPanel.add(new HTML("&nbsp;", true));
		this.sts = sts;
		if (sts != null) {
			if (sts.getTsMetadata() != null) {
				showTS(sts.getTsMetadata());
			}
		}
		initComponent(mainPanel);
		mainPanel.layout(true);
	}


	/**
	 * called when dropped a TS on the area
	 * @param toShow the TS to show
	 */
	public void showTS(TimeSeriesinfo toShow) {
		mainPanel.removeAll();
		mainPanel.removeStyleName("timeseriesArea_bg");
		tableContainer.removeAll();
	
		metadata.setWidget(0, 0, new HTML("<b>TS name:</b>", true));
		metadata.setWidget(0, 1, new HTML(toShow.getTitle()));
		metadata.setWidget(1, 0, new HTML("<b>Creation Date:</b> ", true));
		metadata.setWidget(1, 1, new HTML(toShow.getTimeSeriesCreationDate()));
		metadata.setWidget(2, 0, new HTML("<b>Total rows:</b>", true));
		metadata.setWidget(2, 1, new HTML(""+toShow.getDimension()));

		
		List<String> headers = toShow.getHeaderLabels();
		flexTable = new FlexTable();

		int n = (headers.size() > 10) ? 10 : headers.size();		

		for (int i = 0; i < n ; i++) {
			flexTable.getCellFormatter().setStyleName(0, i, "timeSeries_header");
			flexTable.setWidget(0, i, new HTML(headers.get(i)));
			flexTable.setWidget(1, i, new HTML(".."));
			flexTable.getCellFormatter().setStyleName(1, i, "timeSeries_td");
		}
		if (headers.size() > 10) {
			flexTable.setWidget(0, 11, new HTML(" more .."));
			flexTable.setWidget(1, 11, new HTML(".."));
			flexTable.getCellFormatter().setStyleName(0, 11, "timeSeries_header");
			flexTable.getCellFormatter().setStyleName(1, 11, "timeSeries_td");
		}

		tableContainer.add(flexTable);

		mainPanel.add(metadata);
		mainPanel.add(tableContainer);

		Button moreDetails = new Button("View Timeseries Metadata");
		Button filter = new Button("Filter Table");
		Button showSample = new Button("Show Sample");

		HorizontalPanel buttonsPanel = new HorizontalPanel();
		buttonsPanel.setSpacing(5);
		buttonsPanel.add(moreDetails);
		buttonsPanel.add(filter);
		buttonsPanel.add(showSample);

		mainPanel.add(buttonsPanel);

		moreDetails.addClickHandler(viewMetadataTS);
		showSample.addClickHandler(showTSSample);
		filter.addClickHandler(applyFilterTs);

		//TODO: check this
		presenter.storeChangeInSession(this);
		mainPanel.layout(true);
	}

	ClickHandler viewMetadataTS = new ClickHandler() {
		public void onClick(ClickEvent event) {
			TimeSeriesDialog dlg = new TimeSeriesDialog(sts.getTsMetadata());
			dlg.setAnimationEnabled(true);
			dlg.show();
		}

	};
	
	ClickHandler applyFilterTs = new ClickHandler() {

		public void onClick(ClickEvent event) {
			TimeSeriesFilterDialog dlg = new TimeSeriesFilterDialog(singleton, sts);
			//dlg.setPopupPosition(sender.getAbsoluteLeft(), sender.getAbsoluteTop());
			dlg.setAnimationEnabled(true);
			dlg.show();
		}

	};

	ClickHandler showTSSample = new ClickHandler() {
		public void onClick(ClickEvent event) {	
			presenter.getModel().getModelService().getSampleTimeSeries(sts, new AsyncCallback<Table>() {
				public void onFailure(Throwable caught) {	Window.alert("There were Problem contacting Server, please try later");}

				public void onSuccess(Table result) {
					Table toPass = result;		
					TimeSeriesSampleDialog dlg = new TimeSeriesSampleDialog(toPass);
					dlg.setAnimationEnabled(true);
					dlg.show();							
				}				
			});
		}
	};
	/**
	 * 
	 * @param droppedTS the dropped timeseries
	 */
	public void dropTS(GWTTimeSeries droppedTS) 	{
		idInBasket = droppedTS.getId();
		TimeSeriesinfo tsMetadata = convertWSTS2SerialazableTS(droppedTS);
		sts = new RepTimeSeries(null, tsMetadata);
		GWT.log("showTS TS");
		showTS(tsMetadata);
	}

	public void fetchTS(String identifier, boolean isInteralImage, boolean fullDetails) {
		GWT.log("FETCH TS");
		this.mask("fetching TimeSeries, pleas wait", "loading-indicator");
		
		ReportGenerator.get().getWSTreeService().getTimeSeriesById(identifier, new AsyncCallback<GWTWorkspaceItem>() {
			public void onSuccess(GWTWorkspaceItem result) {
				unmask();
				GWTTimeSeries ts = (GWTTimeSeries) result;
				dropTS(ts);
			}
			public void onFailure(Throwable caught) {
				unmask();	
				Window.alert("Could not fetch Time Series from infrastructure " + caught.getCause());
			}
		});
	}

	/**
	 * converts the WorkSpace TS Object into a Report TS Object
	 * @param md the TS metadata to convert
	 * @return
	 */
	private TimeSeriesinfo convertWSTS2SerialazableTS(GWTTimeSeries md) {
		TimeSeriesinfo tsMetadata = new TimeSeriesinfo(md.getId(), md.getName(), md.getDescription(), md.getOwner(), 
				md.getCreationTime(), md.getLastModificationTime(), md.getTimeSeriesId(), md.getTitle(), md.getCreator(),
				md.getTimeSeriesDescription(), md.getTimeSeriesCreationDate(), 
				md.getPublisher(), md.getSourceId(), md.getSourceName(), md.getRights(), md.getDimension(), md.getHeaderLabels());

		return tsMetadata;				
	}

	/**
	 * refresh the headers once the TS has been filtered
	 */
	public void refreshHeaders() {
		tableContainer.removeAll();
		flexTable = new FlexTable();
		
		List<String> filteredHeaders = new LinkedList<String>();
		TimeSeriesFilter tf = sts.getFilter();
		
		for (Integer colNo : tf.getColsNumberToShow()) {
			String toAdd = sts.getTsMetadata().getHeaderLabels().get(colNo);
			filteredHeaders.add(toAdd);
		}
		
		
		int n = (filteredHeaders.size() > 10) ? 10 : filteredHeaders.size();		

		for (int i = 0; i < n ; i++) {
			flexTable.getCellFormatter().setStyleName(0, i, "timeSeries_header");
			flexTable.setWidget(0, i, new HTML(filteredHeaders.get(i)));
			flexTable.setWidget(1, i, new HTML(".."));
			flexTable.getCellFormatter().setStyleName(1, i, "timeSeries_td");
		}
		if (filteredHeaders.size() > 10) {
			flexTable.setWidget(0, 11, new HTML(" more .."));
			flexTable.setWidget(1, 11, new HTML(".."));
			flexTable.getCellFormatter().setStyleName(0, 11, "timeSeries_header");
			flexTable.getCellFormatter().setStyleName(1, 11, "timeSeries_td");
		}

		tableContainer.add(flexTable);
		Grid newGrid = new Grid(1, 2);
		newGrid.setWidget(0, 0, new HTML("<b>Selected Interval:</b> ", true));
		newGrid.setWidget(0, 1, new HTML(tf.getFrom() + " - " + tf.getTo() ));
		tableContainer.add(newGrid);

	}
	/**
	 * 
	 * @return the possible content
	 */
	public Label getLabel() {
		return label;
	}

	/**
	 * 
	 * @param label set the label
	 */
	public void setLabel(Label label) {
		this.label = label;
	}


	/**
	 * 
	 * @return .
	 */
	public String getIdInBasket() {
		return idInBasket;
	}

	/**
	 * 
	 * @param idInBasket .
	 */
	public void setIdInBasket(String idInBasket) {
		this.idInBasket = idInBasket;
	}

	/**
	 * 
	 * @return .
	 */
	public RepTimeSeries getSts() {
		return sts;
	}

	/**
	 * 
	 * @param sts .
	 */
	public void setSts(RepTimeSeries sts) {
		this.sts = sts;
	}

	/**
	 * 
	 * @param tsf the new ts filter
	 */
	public void setNewFilter(TimeSeriesFilter tsf) {
		this.sts.setFilter(tsf);
	}
}
