package eu.dnetlib.client.widgets;

import com.github.gwtbootstrap.client.ui.base.IconAnchor;
import com.github.gwtbootstrap.client.ui.constants.AlternateSize;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.*;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.sencha.gxt.widget.core.client.info.Info;
import eu.dnetlib.goldoa.domain.Request;
import eu.dnetlib.goldoa.domain.RequestSort;
import eu.dnetlib.goldoa.domain.RequestSortOrder;
import eu.dnetlib.goldoa.domain.Vocabulary;

import java.util.List;

/**
 * Created by stefania on 3/2/15.
 */
public class AutoCompleteWidget implements IsWidget {

    private FlowPanel contentPanel = new FlowPanel();

    private TextBox filter = new TextBox();
    private FlowPanel suggestionList = new FlowPanel();

    private AutoCompleteServiceAsync autoCompleteVocabularyService = GWT.create(AutoCompleteService.class);

    private int minimumNumberOfCharacters = 3;

    private AutoCompleteListener autoCompleteListener;

    private Timer timer;

    public AutoCompleteWidget(final String type, String placeholder) {

        contentPanel.addStyleName("autoCompleteWidget");

        filter.addStyleName("filterTextBox");
        filter.setPlaceholder(placeholder);
        filter.setAlternateSize(AlternateSize.XLARGE);

        filter.setValueChangeHandler(new ValueChangeHandler() {
            @Override
            public void handle(final ValueChangeEvent valueChangeEvent) {

                suggestionList.clear();

                if(valueChangeEvent.getNewValue().length()<minimumNumberOfCharacters) {

                    Label label = new Label();
                    label.addStyleName("suggestionInfoItem");
                    suggestionList.add(label);

                    if(minimumNumberOfCharacters-valueChangeEvent.getNewValue().length()==1) {
                        label.setText("Please add 1 more character");
                    } else {
                        label.setText("Please add " + (minimumNumberOfCharacters-valueChangeEvent.getNewValue().length()) + " more characters");
                    }

                } else {

                    if(timer==null) {

                        timer = new Timer() {

                            @Override
                            public void run() {
                                createSuggestionList(type, valueChangeEvent.getNewValue());
                            }
                        };
                        timer.schedule(300);

                    } else {

                        timer.cancel();
                        timer = new Timer() {

                            @Override
                            public void run() {
                                createSuggestionList(type, valueChangeEvent.getNewValue());
                            }
                        };
                        timer.schedule(300);
                    }
                }
            }
        });

        suggestionList.addStyleName("suggestionList");

        contentPanel.add(filter);

        filter.addFocusHandler(new FocusHandler() {
            @Override
            public void onFocus(FocusEvent event) {

                suggestionList.clear();

                filter.selectAll();

                int filterValueLength = filter.getValue().trim().length();
                if(filterValueLength < minimumNumberOfCharacters) {

                    Label label = new Label();
                    label.addStyleName("suggestionInfoItem");
                    suggestionList.add(label);

                    if(minimumNumberOfCharacters-filterValueLength==1) {
                        label.setText("Please add 1 more character");
                    } else {
                        label.setText("Please add " + (minimumNumberOfCharacters-filterValueLength) + " more characters");
                    }
                } else {
                    createSuggestionList(type, filter.getValue().trim());
                }

                contentPanel.add(suggestionList);
            }
        });

        filter.addBlurHandler(new BlurHandler() {
            @Override
            public void onBlur(BlurEvent event) {
                Timer timer = new Timer() {
                    @Override
                    public void run() {
                        contentPanel.remove(suggestionList);
                    }
                };
                timer.schedule(50);
            }
        });
    }


    @Override
    public Widget asWidget() {
        return contentPanel;
    }

    public void setValue(String value) {
        filter.setValue(value, false);
    }

    public interface AutoCompleteListener {
        public void valueSelected(Vocabulary vocabulary);
    }

    public void setAutoCompleteListener(AutoCompleteListener autoCompleteListener) {
        this.autoCompleteListener = autoCompleteListener;
    }

    private void createSuggestionList(String type, String matchString) {

        autoCompleteVocabularyService.getAutoCompleteVocabulary(type, matchString, new AsyncCallback<List<Vocabulary>>() {

            @Override
            public void onFailure(Throwable caught) {
                //TODO what???
            }

            @Override
            public void onSuccess(List<Vocabulary> vocabularyList) {

                FlowPanel suggestionList = new FlowPanel();

                if (!vocabularyList.isEmpty()) {
                    for (final Vocabulary vocabulary : vocabularyList) {

                        Anchor anchor = new Anchor();
                        anchor.setText(vocabulary.getName());
                        anchor.getElement().setId(vocabulary.getId());
                        anchor.addStyleName("suggestionItem");
                        anchor.addMouseDownHandler(new MouseDownHandler() {
                            @Override
                            public void onMouseDown(MouseDownEvent mouseDownEvent) {
                                filter.setValue(vocabulary.getName());
                                if(autoCompleteListener!=null)
                                    autoCompleteListener.valueSelected(vocabulary);
                            }
                        });
                        suggestionList.add(anchor);
                    }
                } else {
                    Label label = new Label("No results found");
                    label.addStyleName("suggestionInfoItem");
                    suggestionList.add(label);
                }

                suggestionList.addStyleName("suggestionList");
                contentPanel.remove(AutoCompleteWidget.this.suggestionList);
                contentPanel.add(suggestionList);
                AutoCompleteWidget.this.suggestionList = suggestionList;
            }
        });
    }

    public void addStyleName(String styleName) {
        contentPanel.addStyleName(styleName);
    }

    public String getValue() {
        return filter.getValue().trim();
    }

    public void setVisible(boolean visible) {
        filter.setVisible(visible);
    }
}
