package eu.dnetlib.client.shared;

import java.util.HashMap;
import java.util.List;
import java.util.logging.Logger;

import com.google.gwt.dom.client.Style.Clear;
import com.google.gwt.dom.client.Style.Float;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.editor.client.EditorError;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
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.http.client.URL;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DisclosurePanel;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Widget;
import com.sencha.gxt.widget.core.client.form.TextField;
import com.sencha.gxt.widget.core.client.form.validator.AbstractValidator;

import eu.dnetlib.client.shared.GwtFieldLabel.GwtLabelAlign;

public class TitleAndAlias implements IsWidget {
	private final FlowPanel panel = new FlowPanel();
	private TextField titleTextField = new TextField();
	private final TextField aliasTextField = new TextField();
	private String id;
	private String titleEmptyText = "Write title here...";
	private static Logger log = Logger.getLogger("TitleAndAlias.java");

	private HTML titleMessage = new HTML();
	private HTML aliasMessage = new HTML();
	private HTML urlEncodeMessage = new HTML();

	protected StartUpComponents startUpComponents;
	private DisclosurePanel aliasDisclosurePanel = new DisclosurePanel();
	private Button aliasButton = new Button("Add alias");

	private HTML aliasErrorSign = new HTML();
	private DisclosurePanel titleMessageDeclosure = new DisclosurePanel();
	private DisclosurePanel aliasMessageDeclosure = new DisclosurePanel();
	private DisclosurePanel urlEncodeMessageDeclosure = new DisclosurePanel();

	private boolean changed = false;

	public TitleAndAlias(StartUpComponents startUpComponents, boolean onlyTitle) {
		this.startUpComponents = startUpComponents;
		panel.setStyleName("titleAndAlias");
		this.startUpComponents = startUpComponents;
		titleTextField.setStyleName("templateTitleEdit");
		titleTextField.setEmptyText(titleEmptyText);
		titleTextField.addValidator(new MyEmptyValidator());

		panel.add(titleMessageDeclosure);
		FlowPanel fpTitle = new FlowPanel();
		fpTitle.add(titleTextField);
		fpTitle.addStyleName("aliasTitle");
		titleMessage.getElement().getStyle().setClear(Clear.BOTH);
		HorizontalPanel hp = new HorizontalPanel();
		hp.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);

		hp.add(aliasErrorSign);
		titleTextField.getElement().getStyle().setFloat(Float.LEFT);
		hp.getElement().getStyle().setFloat(Float.RIGHT);

		fpTitle.add(hp);

		hp.getElement().getStyle().setMarginTop(10, Unit.PX);
		if (!onlyTitle) {
			hp.add(aliasButton);
		}
		panel.add(fpTitle);

		titleTextField.setWidth("450");
		titleTextField.addStyleName("titleTextField");
		titleMessage.setStyleName("titleMessage myAlerts alert alert-error");
		titleMessage.setHTML("<b>Title cannot be empty.</b>");
		titleTextField.addKeyDownHandler(new KeyDownHandler() {
			public void onKeyDown(KeyDownEvent arg0) {
				titleTextField.validate();
			}
		});
		titleTextField.addKeyUpHandler(new KeyUpHandler() {
			public void onKeyUp(KeyUpEvent arg0) {
				titleTextField.validate();
			}
		});

		aliasErrorSign.setHTML("<b><span class='glyphicon glyphicon-warning-sign' style='color:#b94a48; cursor:pointer;'></span></b>");
		aliasErrorSign.setVisible(false);
		titleTextField.addChangeHandler(new ChangeHandler() {

			public void onChange(ChangeEvent arg0) {
				setChanged(true);
			}
		});
		if (!onlyTitle) {
			aliasTextField.addChangeHandler(new ChangeHandler() {

				public void onChange(ChangeEvent arg0) {
					setChanged(true);
				}
			});

			aliasMessage.setStyleName("aliasMessage myAlerts alert alert-error");
			aliasMessage.setHTML("<b><span class='glyphicon glyphicon-warning-sign'></span>&nbspAlias has to be unique.</b>");
			urlEncodeMessage.setStyleName("aliasMessage myAlerts alert alert-warning");
			urlEncodeMessage.setHTML("<b><span class='glyphicon glyphicon-warning-sign'></span>&nbspAlias may have utf-8 characters and may not be readable from some browsers.</b>");
			// Custom Validator
			aliasTextField.addValidator(new UniqueAliasValidator());
			aliasTextField.addValidator(new Utf8Validator(aliasTextField));
			aliasTextField.focus();

			GwtFieldLabel fl = new GwtFieldLabel(aliasTextField, "Alias", GwtLabelAlign.LEFT);
			fl.setWidgetAlignCenter();
			FlowPanel fpAlias = new FlowPanel();
			aliasMessageDeclosure.setContent(aliasMessage);
			urlEncodeMessageDeclosure.setContent(urlEncodeMessage);
			fpAlias.add(aliasMessageDeclosure);
			fpAlias.add(urlEncodeMessageDeclosure);
			fpAlias.add(fl);
			fl.getLabelPanel().setStyleName("aliasField");

			aliasButton.setHTML("<span class='glyphicon glyphicon-tag' style='font-size:12px'></span>");
			aliasButton.setStyleName("btn btn-info");
			aliasButton.setTitle("Add alias for the VE url...");
			aliasButton.addClickHandler(new ClickHandler() {
				public void onClick(ClickEvent arg0) {
					aliasDisclosurePanel.setOpen(!aliasDisclosurePanel.isOpen());
				}
			});
			fpAlias.addStyleName("aliasDisclosureContent");
			aliasDisclosurePanel.getElement().getStyle().setClear(Clear.BOTH);
			aliasDisclosurePanel.setAnimationEnabled(true);
			aliasDisclosurePanel.setContent(fpAlias);
			aliasDisclosurePanel.setOpen(false);
			panel.add(aliasDisclosurePanel);
			aliasDisclosurePanel.addStyleName("center");
			aliasTextField.setWidth("250");
			aliasTextField.addStyleName("aliasTextField");
			aliasTextField.addKeyDownHandler(new KeyDownHandler() {
				public void onKeyDown(KeyDownEvent arg0) {
					aliasTextField.validate();
				}
			});
			aliasTextField.addKeyUpHandler(new KeyUpHandler() {
				public void onKeyUp(KeyUpEvent arg0) {
					aliasTextField.validate();
				}
			});
			urlEncodeMessage.setVisible(false);

		}

		urlEncodeMessageDeclosure.setAnimationEnabled(true);
		aliasMessageDeclosure.setAnimationEnabled(true);
		urlEncodeMessageDeclosure.setOpen(false);
		aliasMessageDeclosure.setOpen(false);
		titleMessageDeclosure.setContent(titleMessage);
		titleMessageDeclosure.setOpen(false);
		titleMessageDeclosure.setAnimationEnabled(true);
		titleMessageDeclosure.getElement().getStyle().setClear(Clear.BOTH);
		titleMessageDeclosure.addStyleName("center");
		titleTextField.focus();
		aliasErrorSign.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent arg0) {
				aliasDisclosurePanel.setOpen(!aliasDisclosurePanel.isOpen());
			}
		});

	}

	public void showErrorSign() {
		// red
		aliasErrorSign.setHTML("<b><span class='glyphicon glyphicon-warning-sign' style='color:#b94a48; cursor:pointer;'></span></b>");
		aliasErrorSign.setVisible(true);
	}

	public void showWarningSign() {
		// yellow
		aliasErrorSign.setHTML("<b><span class='glyphicon glyphicon-warning-sign' style='color:#c09853; cursor:pointer;'></span></b>");
		aliasErrorSign.setVisible(true);
	}

	public TitleAndAlias(StartUpComponents startUpComponents) {
		this(startUpComponents, false);
	}

	public class UniqueAliasValidator extends AbstractValidator<String> {
		public List<EditorError> validate(Editor<String> field, String value) {
			List<EditorError> errors = null;
			String alias = aliasTextField.getText();
			if (alias != null && !alias.isEmpty() && (!isUnique(alias))) {
				errors = createError(field, "This alias is already used...", value);
				aliasMessageDeclosure.setOpen(true);
				urlEncodeMessageDeclosure.setOpen(false);
				showErrorSign();
			} else {

				aliasErrorSign.setVisible(false);

				aliasMessageDeclosure.setOpen(false);
				validateEncoding(alias);
			}
			return errors;
		}
	}

	public class Utf8Validator extends AbstractValidator<String> {
		private TextField textField;

		public Utf8Validator(TextField textField) {
			this.textField = textField;
		}

		// ********** UTF8 ************
		public List<EditorError> validate(Editor<String> field, String value) {
			List<EditorError> errors = null;
			String alias = textField.getText();

			validateEncoding(alias);

			return errors;
		}
	}

	public void validateEncoding(String alias) {

		if (alias != null && !alias.isEmpty() && URL.encode(skipCharacters(alias)) != null && URL.encode(skipCharacters(alias)).contains("%")) {
			if (!aliasErrorSign.isVisible()) {
				showWarningSign();
				urlEncodeMessageDeclosure.setOpen(true);
			}
		} else {
			if (!aliasMessageDeclosure.isOpen()) {
				aliasErrorSign.setVisible(false);
				urlEncodeMessageDeclosure.setOpen(false);
			}
		}

	}

	public class MyEmptyValidator extends AbstractValidator<String> {
		public List<EditorError> validate(Editor<String> field, String value) {
			List<EditorError> errors = null;
			if (titleTextField.getText() == null || titleTextField.getText().isEmpty() || titleTextField.getText().equals(titleEmptyText)) {
				errors = createError(field, "Title is a required field...", value);
				titleMessageDeclosure.setOpen(true);
			} else {
				titleMessageDeclosure.setOpen(false);
			}
			return errors;
		}
	}

	private boolean isUnique(String alias) {
		String usedId = null;
		if (startUpComponents.getAliasIds().containsKey(alias)) {
			usedId = startUpComponents.getAliasIds().get(alias);
			log.info("ALIAS exists........... " + alias + " id: " + usedId);
		}
		if (usedId == null) {
			return true;
		}
		if (id != null) {
			if (usedId.equals(id)) {
				return true;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}

	public void convert() {
		if ((aliasTextField.getText() == null || aliasTextField.getText().isEmpty()) && !titleTextField.getText().equals(titleEmptyText)) {
			aliasTextField.setText(titleTextField.getText());
			setChanged(true);
		}
		try {
			String converted = skipCharacters(aliasTextField.getText());
			aliasTextField.setText(converted);
		} catch (Exception e) {
			e.printStackTrace();
			log.info("error in convert~~~~~~~~~~~~~~~~~~`");
		}

	}

	public String skipCharacters(String alias) {
		try {
			String v = alias.trim();
            v=v.replace(" ", "-");
			v = v.replaceAll("[~`!@#$%^&*()_+=|:;,.'<>/?]", "");
			v = v.replace("\\", "");
			v = v.replaceAll("\"", "");
			return v;
		} catch (Exception e) {
			e.printStackTrace();
			log.info("error in convert~~~~~~~~~~~~~~~~~~`");
		}
		return null;
	}

	public static void updateAliasMap(String ComponentId, String oldAlias, String newAlias, HashMap<String, String> alias) {
		if (oldAlias != null) {
			alias.remove(oldAlias);
		}
		if (newAlias != null) {
			alias.put(newAlias, ComponentId);
		}
	}

	public void hideErrorsAndWarnings() {
		aliasErrorSign.setVisible(false);
		titleMessageDeclosure.setOpen(false);
		aliasDisclosurePanel.setOpen(false);
		aliasMessageDeclosure.setOpen(false);
		urlEncodeMessageDeclosure.setOpen(false);
		try {
			titleTextField.clearInvalid();
			aliasTextField.clearInvalid();
		} catch (Exception e) {
			log.info("EROOOORRRRR hideErrorsAndWarnings ");
		}
	}

	public Widget asWidget() {
		return panel;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public FlowPanel getPanel() {
		return panel;
	}

	public TextField getTitleTextField() {
		return this.titleTextField;
	}

	public TextField getAliasTextField() {
		return aliasTextField;
	}

	public DisclosurePanel getAliasDisclosurePanel() {
		return aliasDisclosurePanel;
	}

	public boolean isChanged() {
		return changed;
	}

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

}
