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

import java.util.ArrayList;
import java.util.List;

import org.gcube.portlets.d4sreporting.common.shared.BasicComponent;
import org.gcube.portlets.d4sreporting.common.shared.Metadata;
import org.gcube.portlets.user.reportgenerator.client.ReportGenerator;
import org.gcube.portlets.user.reportgenerator.client.Presenter.Presenter;
import org.gcube.portlets.user.reportgenerator.client.model.TemplateComponent;
import org.gcube.portlets.user.reportgenerator.client.model.TemplateModel;
import org.gcube.portlets.user.workspace.client.workspace.GWTWorkspaceItem;
import org.gcube.portlets.user.workspace.client.workspace.folder.item.GWTExternalImage;
import org.gcube.portlets.user.workspace.client.workspace.folder.item.gcube.GWTImageDocument;
import org.gcube.portlets.widgets.lighttree.client.ItemType;
import org.gcube.portlets.widgets.lighttree.client.event.PopupEvent;
import org.gcube.portlets.widgets.lighttree.client.event.PopupHandler;
import org.gcube.portlets.widgets.lighttree.client.load.WorkspaceLightTreeLoadPopup;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.RunAsyncCallback;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
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.Composite;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;


/**
 *
 * @author Massimiliano Assante, ISTI-CNR - massimiliano.assante@isti.cnr.it
 */
public class ClientImage extends Composite {

	private String expectedContent = "";

	private final String METADATA_TITLE_KEY = "title";
	private final String METADATA_DESC_KEY = "description";
	private final String METADATA_SOURCE_KEY = "source";
	
	private int imageWidth;
	private int imageHeight;

	private FocusPanel focusPanel = new FocusPanel();
	private VerticalPanel mainPanel = new VerticalPanel();
	private SimplePanel imagePanel = new SimplePanel();
	private Image currImage;
	private Presenter presenter;

	private String idInBasket;

	private String currentUser;
	private String currentScope;

	public static final int DEFAULT_HEIGHT = 100;
	public static final int DEFAULT_WIDTH = 700;

	private TextBox titleTB = new TextBox();
	private TextBox descTB = new TextBox();
	private TextBox sourceTB = new TextBox();
	
	private Button resetB = new Button("Clear");
	private Button addImageB = new Button("Select Image");
	private Button uploadImageB = new Button("Upload Image");
	private Button removeB = new Button("Remove Image");
	private BasicComponent basicComponent;
	/**
	 * 
	 * @param presenter
	 * @param width
	 * @param tag
	 */
	public ClientImage(BasicComponent co, Presenter presenter, int width, int height, boolean isRemovable, TextTableImage owner) {
		imageHeight = height;
		imageWidth = width;
		this.presenter = presenter;
		this.basicComponent = co;
		HorizontalPanel controlPanel = getControlPanel(isRemovable, owner);
		VerticalPanel attributesPanel = getAttributesPanel(co);
		mainPanel.add(controlPanel);
		mainPanel.add(imagePanel);
		mainPanel.add(attributesPanel);		

		mainPanel.setWidth((TemplateModel.TEMPLATE_WIDTH-95)+"px");
		imagePanel.setSize(DEFAULT_WIDTH+"px", DEFAULT_HEIGHT+"px");
		attributesPanel.setWidth((TemplateModel.TEMPLATE_WIDTH-95)+"px");

		mainPanel.setStyleName("imageWrapperPanel");
		imagePanel.setStyleName("imagePanel");
		controlPanel.setStyleName("tableControlPanel");
		attributesPanel.setStyleName("tableAttributesPanel");

		String imageURL = (String) co.getPossibleContent();
		
		if (imageURL == null || imageURL.trim().compareTo("") == 0 || imageURL.endsWith(TemplateComponent.DEFAULT_IMAGE_NAME)) {
			GWT.log("Empty ImageUrl="+imageURL);			
			imagePanel.addStyleName("imageEmptyPanel");
		}
		else {			
			GWT.log("Found ImageUrl="+imageURL);
			showImage(new Image(imageURL), width, height);
		}
		
		//set style for buttons
		for (int i = 0; i < controlPanel.getWidgetCount(); i++) {
			if (controlPanel.getWidget(i) instanceof Button) {
				Button b = (Button) controlPanel.getWidget(i);
				b.addStyleName("tableButton");
			}
		}
		if (isRemovable) {
			removeB.removeStyleName("tableButton");
			removeB.addStyleName("deleteEntryButton");
			removeB.getElement().getStyle().setMarginRight(10, Unit.PX);
		}

		focusPanel.add(mainPanel);
		initWidget(focusPanel);

		focusPanel.addMouseOutHandler(new MouseOutHandler() {			
			@Override
			public void onMouseOut(MouseOutEvent event) {
				saveStatus();
			}
		});
	}
	
	private HorizontalPanel getControlPanel(boolean isRemovable, final TextTableImage owner) {
		final HorizontalPanel toReturn = new HorizontalPanel();

		removeB.addClickHandler(new ClickHandler() {			
			@Override
			public void onClick(ClickEvent event) {
				if (owner != null) {
					 remove(owner);
				}
			}
		});
		
		resetB.addClickHandler(new ClickHandler() {			
			@Override
			public void onClick(ClickEvent event) {
				titleTB.setText("");
				descTB.setText("");
				sourceTB.setText("");
				showImage(new Image(TemplateComponent.DEFAULT_IMAGE_NAME), DEFAULT_WIDTH, DEFAULT_HEIGHT);	
				imagePanel.addStyleName("imageEmptyPanel");
			}
		});

		addImageB.addClickHandler(new ClickHandler() {			
			@Override
			public void onClick(ClickEvent event) {
				openFileExplorer(addImageB.getAbsoluteLeft(), addImageB.getAbsoluteTop());
			}
		});
		
		uploadImageB.addClickHandler(new ClickHandler() {			
			@Override
			public void onClick(ClickEvent event) {
				presenter.showUploadFilePopup();
			}
		});

		toReturn.setSpacing(3);
		if (isRemovable)
			toReturn.add(removeB);	
		toReturn.add(resetB);
		toReturn.add(uploadImageB);
		toReturn.add(addImageB);
		
		return toReturn;
	}
	
	private VerticalPanel getAttributesPanel(BasicComponent co) {
		VerticalPanel toReturn = new VerticalPanel();
		
		for (Metadata md : co.getMetadata()) {
			if (md.getAttribute().compareTo(METADATA_TITLE_KEY) == 0)
				titleTB.setText(md.getValue());
			if (md.getAttribute().compareTo(METADATA_DESC_KEY) == 0)
				descTB.setText(md.getValue());
			if (md.getAttribute().compareTo(METADATA_SOURCE_KEY) == 0)
				sourceTB.setText(md.getValue());
		}

		HorizontalPanel hp1 = new HorizontalPanel();
		HTML title = new HTML("<div style=\"white-space:nowrap;\">Title: <span style=\"color: red;\">*&nbsp;</span></div>", true);
		hp1.add(title);
		hp1.add(titleTB);
		titleTB.setWidth("135px");
		

		HTML desc = new HTML("&nbsp;Description:&nbsp;", true);
		
		HTML source = new HTML("Source: ", true);
		

		hp1.add(desc);
		hp1.add(descTB);
		descTB.setWidth("435px");
		toReturn.add(hp1);
		
		toReturn.add(source);
		toReturn.add(sourceTB);
		sourceTB.setWidth("693px");
		
		return toReturn;
	}

	public void add(Widget w) {
		mainPanel.add(w);
	}
	/**
	 * called by the select image ws light tree
	 * @param toShow the image to show
	 */
	public void showImage(Image toShow, int width, int height) {
		int checkedWidth = width;
		int checkedHeight = height;
		Double maxWidth = new Double(700);
		GWT.log("OriginalImage W="+checkedWidth+ " H="+checkedHeight);
		if (width > 700) {
			Double resizeFactor = maxWidth / ((double) width);			
			checkedWidth = new Double(width * resizeFactor).intValue();
			checkedHeight = new Double(height * resizeFactor).intValue();
		}
		imagePanel.clear();
		this.currImage = toShow;
		GWT.log("ResizedImage W="+checkedWidth+ " H="+checkedHeight);
		toShow.setWidth(checkedWidth+"px");
		imagePanel.setSize(checkedWidth+"px", checkedHeight+"px");
		imagePanel.add(toShow);
		imageWidth = checkedWidth;
		imageHeight = checkedHeight;
		saveStatus();
	}
	
	/**
	 * called by the constructor
	 * @param toShow the image to show
	 */
	public void showImage(Image toShow) {
		showImage(toShow, toShow.getWidth(), toShow.getHeight());
	}
	private void saveStatus() {
		Metadata title = new Metadata(METADATA_TITLE_KEY, titleTB.getText());
		Metadata desc = new Metadata(METADATA_DESC_KEY, descTB.getText());
		Metadata source = new Metadata(METADATA_SOURCE_KEY, sourceTB.getText());
		List<Metadata> mds = new ArrayList<Metadata>();
		mds.add(title);
		mds.add(desc);
		mds.add(source);
		basicComponent.setMetadata(mds);
		presenter.storeChangeInSession(this);
		GWT.log("Saved in Session");
	}
	
	public List<Metadata> getMetadata() {
		return basicComponent.getMetadata();
	}
	/**
	 * 
	 * @param url .
	 * @param id the id in the folder
	 */
	public void dropImage(String url, String id, int width, int height)	{
		GWT.log("URL:" + url, null);
		idInBasket = id;
		showImage(new Image(url), width, height);
	}

	public void fetchImage(String identifier, final boolean isInteralImage, boolean fullDetails) {
		ReportGenerator.get().getWSTreeService().getImageById(identifier, isInteralImage, fullDetails, new AsyncCallback<GWTWorkspaceItem>() {

			public void onSuccess(GWTWorkspaceItem result) {
				if (isInteralImage) {
					GWTImageDocument image = (GWTImageDocument) result;
					int width = image.getWidth();
					int height = image.getHeight();					
					dropImage(image.getImageUrl(), image.getId(), width, height);
				} else {
					GWTExternalImage image = (GWTExternalImage) result;
					int width = image.getWidth();
					int height = image.getHeight();
					dropImage(image.getImageUrl(), image.getId(), width, height);
				}				
			}
			public void onFailure(Throwable caught) {
				Window.alert("Could not fetch image from infrastructure " + caught.getCause());
			}
		});
	}

	/**
	 * 
	 * @return the image
	 */
	public Image getDroppedImage() {
		if (currImage == null)
			return new Image();
		return currImage;
	}
//
//	/**
//	 * return a URL which is lookable for on the web
//	 * @param imageName .
//	 * @param templateName .
//	 * @return .
//	 */
//	public String getImageURL(String imageName, String templateName) {
//		currentUser = presenter.getCurrentUser().getUsername();
//		currentScope = presenter.getCurrentScope();	
//		/**
//		 * Images will be stored under webapps/usersArea...
//		 * GWT.getModuleBaseURL() returns 	 * e.g. http://dlib28.isti.cnr.it/templatecreator/html/
//		 * need to get just http://dlib28.isti.cnr.it/
//		 */
//		//remove "/html/" and get e.g. http://dlib28.isti.cnr.it/templatecreator
//		String host = GWT.getModuleBaseURL().substring(0, GWT.getModuleBaseURL().length()-6);
//
//		//loog for last slash
//		int lastSlash = host.lastIndexOf("/");
//
//		//get what i need : e.g. http://dlib28.isti.cnr.it/ or  host = "http://localhost:8080/";
//		host = host.substring(0, lastSlash +1 );
//		//host = "http://localhost:8080/";
//
//		String imgURL = host + "usersArea/"	+ currentScope + "/templates/" 
//				+ currentUser + "/CURRENT_OPEN/images/" + imageName;
//
//		return imgURL;
//	}

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

	public int getImageHeight() {
		return imageHeight;
	}
	/**
	 * 
	 * @param idInBasket .
	 */
	public void setIdInBasket(String idInBasket) {
		this.idInBasket = idInBasket;
	}
	/**
	 * 
	 * @return expectedContent
	 */
	public String getExpectedContent() {
		return expectedContent;
	}

	
	public BasicComponent getBasicComponent() {
		return basicComponent;
	}

	/**
	 * 
	 * @param expectedContent .
	 */
	public void setExpectedContent(String expectedContent) {
		this.expectedContent = expectedContent;	
	}

	private void openFileExplorer(final int left, final int top) {
		GWT.runAsync(WorkspaceLightTreeLoadPopup.class, new RunAsyncCallback() {
			public void onSuccess() {

				WorkspaceLightTreeLoadPopup wpTreepopup = new WorkspaceLightTreeLoadPopup("Select the Image", true, true);
				wpTreepopup.setShowableTypes(ItemType.IMAGE_DOCUMENT, ItemType.EXTERNAL_IMAGE);
				wpTreepopup.setSelectableTypes(ItemType.IMAGE_DOCUMENT, ItemType.EXTERNAL_IMAGE);
				wpTreepopup.setWidth("450px");
				wpTreepopup.addPopupHandler(new PopupHandler() {
					public void onPopup(PopupEvent event) {
						if (! event.isCanceled()) {
							if (event.getSelectedItem() != null) {
								if (event.getSelectedItem().getType() == ItemType.IMAGE_DOCUMENT)
									fetchImage(event.getSelectedItem().getId(), true, true);
								else
									fetchImage(event.getSelectedItem().getId(), false, true);
							}									
						}
					}
				});
				wpTreepopup.center();
				wpTreepopup.show();
			}

			public void onFailure(Throwable reason) {
				Window.alert("There are networks problem, please check your connection.");              
			}
		});
	}
	/**
	 * helper method that removes a image from the textTableImage widget
	 * @param owner
	 */
	private void remove(TextTableImage owner) {
		owner.removeFromParent(this);
		removeFromParent();	
	}
}
