package eu.dnetlib.client.shared;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.logging.Logger;

import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.user.client.ui.FlowPanel;
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.Label;
import com.google.gwt.user.client.ui.MultiWordSuggestOracle;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SuggestBox;
import com.google.gwt.user.client.ui.SuggestOracle;
import com.google.gwt.user.client.ui.VerticalPanel;

import eu.dnetlib.efg1914.authoring.components.Frame;
import eu.dnetlib.efg1914.authoring.components.Theme;
import eu.dnetlib.efg1914.authoring.components.Topic;

public class MySuggestBox {
	private SuggestBox suggestBox;
	private MultiWordSuggestOracle oracleWords = new MultiWordSuggestOracle();
	private HorizontalPanel suggestedWordsPanel = new HorizontalPanel();
	final private List<String> suggestedWords = new ArrayList<String>();
	final private FlowPanel suggestions = new FlowPanel();
	private boolean changed = false;
	private static Logger log = Logger.getLogger("SuggestBox.java");
	private VerticalPanel panel = new VerticalPanel();
	private HTML htmlNoRecommendations = new HTML();
	private final String messageText = "Type more recommendations here";

	public MySuggestBox() {
		suggestBox = new SuggestBox(oracleWords);
		// DefaultSuggestionDisplay display = (DefaultSuggestionDisplay)
		// suggestBox.getSuggestionDisplay();
		// display.setSuggestionListHiddenWhenEmpty(false);
		//
		suggestBox.setWidth("250px");
		suggestedWordsPanel.setWidth("320px");

		ScrollPanel scrollsuggestions = new ScrollPanel(suggestions);
		scrollsuggestions.setWidth("315px");
		suggestedWordsPanel.add(scrollsuggestions);
		panel.add(htmlNoRecommendations);
		panel.add(suggestedWordsPanel);
		panel.add(suggestBox);
		suggestBox.getValueBox().addClickHandler(new ClickHandler() {

			public void onClick(ClickEvent arg0) {
				log.info("Click suggest box");
				if (suggestBox.getValueBox().getText().contains(messageText)) {
					suggestBox.getValueBox().setText("");
					log.info("empty");

				}

			}
		});
		suggestBox.getValueBox().addBlurHandler(new BlurHandler() {

			public void onBlur(BlurEvent arg0) {
				log.info("blur suggest box");

				suggestBox.getValueBox().setText(messageText);

			}
		});
		suggestBox.getValueBox().addKeyUpHandler(new KeyUpHandler() {
             public void onKeyUp(KeyUpEvent event) {
            	 if (suggestBox.getValueBox().getText().contains(messageText)&&(event.isLeftArrow()||event.isRightArrow()||event.isUpArrow()||event.isDownArrow())) {
 					suggestBox.getValueBox().setText("");
 					log.info("empty");

 				}
            }
        });

//        suggestBox.getValueBox().addKeyPressHandler(new KeyPressHandler() {
//             
//            public void onKeyPress(KeyPressEvent event) {
//            	 if (suggestBox.getValueBox().getText().contains(messageText)&&(event.isLeftArrow()||event.isRightArrow()||event.isUpArrow()||event.isDownArrow())) {
//  					suggestBox.getValueBox().setText("");
//  					log.info("empty");
//
//  				}
//            }
//        });

        suggestBox.getValueBox().addKeyDownHandler(new KeyDownHandler() {
             
            public void onKeyDown(KeyDownEvent event) {
            	 if (suggestBox.getValueBox().getText().contains(messageText)&&(event.isLeftArrow()||event.isRightArrow()||event.isUpArrow()||event.isDownArrow())) {
  					suggestBox.getValueBox().setText("");
  					log.info("empty");

  				}
            }
        });
	}
 
	public MySuggestBox(final HashMap<String, Frame> resources, int doNothing) {
		this();
		for (Entry<String, Frame> s : resources.entrySet()) {
			String template = s.getValue().getTemplate();
			if (!template.equals("intro") && !template.equals("ft0")&&s.getValue().getTitle()!=null) {
				oracleWords.add(s.getValue().getTitle());
			}
		}
		// Create the suggest box
		suggestBox.addSelectionHandler(new SelectionHandler<SuggestOracle.Suggestion>() {

			public void onSelection(SelectionEvent<SuggestOracle.Suggestion> event) {

				for (Entry<String, Frame> s : resources.entrySet()) {
					if (s.getValue().getTitle().equals(suggestBox.getText()) && !suggestedWords.contains(s.getKey())) {
   							changed = true;
							suggestions.add(addSuggestion(s.getValue().getTitle(), s.getKey()));
							suggestedWords.add(s.getKey());
							break;
						 
					}
				}
				suggestBox.setText("");
				suggestBox.getValueBox().setText(messageText);
				suggestBox.getValueBox().selectAll();

			}

		});
	}

	public MySuggestBox(final HashMap<String, Topic> resources, String doNothing) {
		this();
		for (Entry<String, Topic> s : resources.entrySet()) {
			oracleWords.add(s.getValue().getTitle());
		}
		// Create the suggest box
		suggestBox.addSelectionHandler(new SelectionHandler<SuggestOracle.Suggestion>() {

			public void onSelection(SelectionEvent<SuggestOracle.Suggestion> event) {

				for (Entry<String, Topic> s : resources.entrySet()) {
					if (s.getValue().getTitle().equals(suggestBox.getText()) && !suggestedWords.contains(s.getKey())) {
						changed = true;

						suggestions.add(addSuggestion(s.getValue().getTitle(), s.getKey()));
						suggestedWords.add(s.getKey());
						break;
					}
				}
				suggestBox.setText("");
				suggestBox.getValueBox().setText(messageText);
				suggestBox.getValueBox().selectAll();

			}

		});
	}

	public MySuggestBox(final HashMap<String, Theme> resources) {
		this();
		for (Entry<String, Theme> s : resources.entrySet()) {
			oracleWords.add(s.getValue().getTitle());
		}

		suggestBox.addSelectionHandler(new SelectionHandler<SuggestOracle.Suggestion>() {
			public void onSelection(SelectionEvent<SuggestOracle.Suggestion> event) {
				for (Entry<String, Theme> s : resources.entrySet()) {
					if (s.getValue().getTitle().equals(suggestBox.getText()) && !suggestedWords.contains(s.getKey())) {
						changed = true;
						suggestions.add(addSuggestion(s.getValue().getTitle(), s.getKey()));
						suggestedWords.add(s.getKey());
						break;
					}
				}
				suggestBox.setText("");
				suggestBox.getValueBox().setText( messageText);
				suggestBox.getValueBox().selectAll();

			}
		});
	}

	private HorizontalPanel addSuggestion(final String title, final String ID) {

		final HorizontalPanel hp = new HorizontalPanel();

		hp.setStyleName("suggestions");

		Label name = new Label();
		name.setText(title);

		Image x = new Image("images/close2.png");
		x.setSize("15px", "15px");
		x.addClickHandler(new ClickHandler() {

			public void onClick(ClickEvent event) {
				hp.setVisible(false);
				suggestedWords.remove(ID);
				changed = true;
				if (suggestedWords.size() == 0) {
					htmlNoRecommendations.setHTML("No recommendations.");
				} else {
					htmlNoRecommendations.setHTML("");
				}

			}
		});
		name.getElement().getStyle().setProperty("margin", " 5px 5px 0px 5px");
		x.getElement().getStyle().setProperty("margin", " 5px 5px 0px 5px");

		hp.add(name);
		hp.add(x);

		htmlNoRecommendations.setHTML("");

		return hp;
	}

	private native String getTableMarkup() /*-{
											return [ '<table >',
											'<tr><td class=name ></td><td class=x ></td></tr>', '</table>' ]
											.join("");
											}-*/;

	public SuggestBox getSuggestBox() {
		return suggestBox;
	}

	public HorizontalPanel getSuggestedWordsPanel() {
		return suggestedWordsPanel;
	}

	public void reset() {
		suggestedWords.clear();
		suggestions.clear();
	}

	/*
	 * add a new word to suggest when a new component is created
	 */
	public void addWordToSuggest(String title) {

		oracleWords.add(title);
	}

	/*
	 * update words to suggest when a component is deleted or updated
	 */
	public void updateWordsToSuggest(final HashMap<String, Frame> resources) {
		oracleWords.clear();
		for (Entry<String, Frame> s : resources.entrySet()) {
			String template = s.getValue().getTemplate();
			if (!template.equals("intro") && !template.equals("ft0")) {
				oracleWords.add(s.getValue().getTitle());
			}
		}	
	}
	public void updateWordsToSuggest(final HashMap<String, Topic> resources,int doNothing) {
		oracleWords.clear();
		for (Entry<String, Topic> s : resources.entrySet()) {
			oracleWords.add(s.getValue().getTitle());
		}		
	}
	public void updateWordsToSuggest(final HashMap<String, Theme> resources,boolean doNothing) {
		oracleWords.clear();
		for (Entry<String, Theme> s : resources.entrySet()) {
			oracleWords.add(s.getValue().getTitle());
		}
	}

	public List<String> getSuggestedWords() {
		return this.suggestedWords;
	}

	public void setSuggestedWordsTopics(final List<String> mywords, final HashMap<String, Topic> topics) {
		// rootLogger.log(Level.SEVERE, "Set! Words  1 : " + mywords);
		changed = false;

		// clear panelof words
		this.suggestions.clear();
		// clear list of words
		this.suggestedWords.clear();

		if (mywords != null) {

			for (String id : mywords) {
				if (topics.get(id) != null) {
					suggestions.add(addSuggestion(topics.get(id).getTitle(), id));
					this.suggestedWords.add(id);
				}
			}

		}
		if (this.suggestedWords.size() == 0) {
			htmlNoRecommendations.setHTML("No recommendations.");
		} else {
			htmlNoRecommendations.setHTML("");
		}
		suggestBox.getValueBox().setText(messageText);
		suggestBox.getValueBox().selectAll();

	}

	public void setSuggestedWordsFrames(final List<String> mywords, final HashMap<String, Frame> frames) {
		changed = false;
		// clear panelof words
		this.suggestions.clear();
		// clear list of words
		this.suggestedWords.clear();
		if (mywords != null) {
			for (String id : mywords) {
				if (frames.get(id) != null) {
					if(!frames.get(id).getTemplate().equals("intro")&&!frames.get(id).getTemplate().equals("ft0")){
						suggestions.add(addSuggestion(frames.get(id).getTitle(), id));
						this.suggestedWords.add(id);
					}
				}
			}

		}
		if (this.suggestedWords.size() == 0) {
			htmlNoRecommendations.setHTML("No recommendations.");
		} else {
			htmlNoRecommendations.setHTML("");
		}
		suggestBox.getValueBox().setText(messageText);
		suggestBox.getValueBox().selectAll();
	}

	public void setSuggestedWordsThemes(final List<String> mywords, final HashMap<String, Theme> themes) {
		// rootLogger.log(Level.SEVERE, "Set! Words  1 : " + mywords);
		changed = false;

		// clear panelof words
		this.suggestions.clear();
		// clear list of words
		this.suggestedWords.clear();

		if (mywords != null) {

			for (String id : mywords) {
				if (themes.get(id) != null) {
					suggestions.add(addSuggestion(themes.get(id).getTitle(), id));
					this.suggestedWords.add(id);
				}
			}

		}
		if (this.suggestedWords.size() == 0) {
			htmlNoRecommendations.setHTML("No recommendations.");
		} else {
			htmlNoRecommendations.setHTML("");
		}
		suggestBox.getValueBox().setText(messageText);
		suggestBox.getValueBox().selectAll();

	}

	public boolean isChanged() {
		return changed;
	}

	public void setChanged(boolean changed) {
		this.changed = changed;
	}

	public VerticalPanel getPanel() {
		return panel;
	}

	public MultiWordSuggestOracle getOracleWords() {
		return oracleWords;
	}

}
