package be.msyben.vinylManager.tools.swing;

import be.msyben.vinylManager.tools.Sort;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

/**
 * Combobox personnalisée permettant une suggestion.
 * @author Mathieu Syben
 */
public class SuggestionComboBox2 extends JComponent {
     /** uid     */
    private static final long serialVersionUID = 78553784662L;

    /** Le champs de 'recherche'. */
    private JTextField field;
    /** La liste des suggestions. */
    private JPanel suggestions = new JPanel();
    /** La liste des labels */
    private List<JLabel> labels = new ArrayList<JLabel>();
    /** Le scrollpanel dans lequel se trouve la liste. */
    private JScrollPane suggestionsPane;
    /** Le panel global. */
    private JPanel panel;
    /** La largeur */
    private int width = 0;
    /** La hauteur du champs texte */
    private int textFieldHeight = 0;
    /** La hauteur de la liste. */
    private int listHeight = 0;
    /** La largeur de la liste. */
    private int listWidth = 0;
    /** Indique si on montre la liste */
    private boolean showSuggestions = false;
    /** Toutes les suggestions possibles */
    private List<String> allSuggestions;

    /** Constructeur privé. */
    private SuggestionComboBox2() {
    }

    /**
     * Constructeur.
     * @param allSuggestions Toutes les suggestions.
     */
    public SuggestionComboBox2(List<String> allSuggestions) {
        Sort.sort(allSuggestions);
        this.allSuggestions = allSuggestions;
        placeComponents();
    }

    /**
     * Place les éléments.
     */
    private void placeComponents() {
        panel = new JPanel(null);
        field = new JTextField();

        panel.add(field);
        
        suggestionsPane = new JScrollPane(suggestions);
        suggestionsPane.getVerticalScrollBar().setUnitIncrement(6);
        panel.add(suggestionsPane);


        field.addKeyListener(new KeyAdapter() {

            @Override
            public void keyReleased(KeyEvent e) {

                switch (e.getKeyCode()) {
                    case KeyEvent.VK_UP:
                        if (currentSelection > 0 && currentSelection < labels.size()) {
                            labels.get(currentSelection).setBackground(Color.white);
                            currentSelection--;
                            labels.get(currentSelection).setBackground(Color.cyan);
                        } else {
                            if (!labels.isEmpty()) {
                                labels.get(0).setBackground(Color.white);
                                currentSelection = labels.size() - 1;
                                labels.get(currentSelection).setBackground(Color.cyan);
                            }
                        }

                        double position = (currentSelection * 1.0) / (labels.size() * 1.0);
                        int positionNeeded = (int) (suggestionsPane.getVerticalScrollBar().getMaximum() * position);
                        suggestionsPane.getVerticalScrollBar().setValue(positionNeeded);

                        break;
                    case KeyEvent.VK_DOWN:
                        if (currentSelection >= 0 && currentSelection < labels.size() - 1) {
                            labels.get(currentSelection).setBackground(Color.white);
                            currentSelection++;
                            labels.get(currentSelection).setBackground(Color.cyan);
                        } else {
                            if (!labels.isEmpty()) {
                                labels.get(labels.size() - 1).setBackground(Color.white);
                                currentSelection = 0;
                                labels.get(currentSelection).setBackground(Color.cyan);
                            }
                        }

                        position = (currentSelection * 1.0) / (labels.size() * 1.0);
                        positionNeeded = (int) (suggestionsPane.getVerticalScrollBar().getMaximum() * position);
                        suggestionsPane.getVerticalScrollBar().setValue(positionNeeded);

                        break;
                    case KeyEvent.VK_ENTER:
                        if (currentSelection >= 0 && currentSelection < labels.size()) {
                            field.setText(labels.get(currentSelection).getText());
                        }
                        hideSuggestions();
                        break;
                    default:
                        if (field.getText() != null && field.getText().length() > 0) {
                            showSuggestions();
                        } else {
                            hideSuggestions();
                        }
                }
            }
        });

        field.addFocusListener(new FocusAdapter() {

            @Override
            public void focusLost(FocusEvent e) {
                hideSuggestions();
            }
        });

        add(panel);
    }
    private int currentSelection = -1;

    /**
     * Calcule les suggestions correspondant à la recherche et les mets dans la liste.
     * Renvoie le nombre de suggestion.
     */
    private void computeSuggestions() {
        String cont = field.getText().toLowerCase();
        List<String> oks = new ArrayList<String>();
        for (String s : allSuggestions) {
            if (s.toLowerCase().contains(cont)) {
                oks.add(s);
            }
        }

        labels.clear();
        suggestions.removeAll();

        suggestions.setLayout(new GridLayout(oks.size(), 1));
        suggestions.setSize(listWidth, oks.size() * 17);
        if (oks.size()*17 < listHeight) {
            suggestionsPane.setSize(listWidth,  5 + oks.size() * 17);

        } else {
            suggestionsPane.setSize(listWidth,  listHeight);
        }

        for (int i = 0; i < oks.size(); i++) {
            final int j = i;
            final JLabel lab = new JLabel(oks.get(i));
            lab.setBackground(Color.white);
            lab.setOpaque(true);
            lab.addMouseListener(new MouseAdapter() {

                @Override
                public void mouseClicked(MouseEvent e) {
                    field.setText(lab.getText());
                    hideSuggestions();
                }

                @Override
                public void mouseEntered(MouseEvent e) {
                    lab.setBackground(Color.cyan);
                    currentSelection = j;
                }

                @Override
                public void mouseExited(MouseEvent e) {
                    lab.setBackground(Color.white);
                }
            });

            lab.setSize(width, 17);
            suggestions.add(lab);
            labels.add(lab);
        }
    }

    /**
     * Définit la taille.
     * @param width la largeur.
     * @param textFieldHeight La hauteur du champs texte.
     * @param listHeight La hauteur de la liste.
     */
    public void setSize(int width, int textFieldHeight, int listHeight) {

        setSize(width, textFieldHeight, listHeight, width);

    }
    

    /**
     * Définit la taille.
     * @param width la largeur.
     * @param textFieldHeight La hauteur du champs texte.
     * @param listHeight La hauteur de la liste.
     */
    public void setSize(int width, int textFieldHeight, int listHeight, int listWidth) {

        this.width = width;
        this.listWidth = listWidth;
        this.textFieldHeight = textFieldHeight;
        this.listHeight = listHeight;

        if (showSuggestions) {
            panel.setSize(Math.max(width, listWidth), textFieldHeight + listHeight);
            setSize(Math.max(width, listWidth), textFieldHeight + listHeight);
        } else {
            panel.setSize(width, textFieldHeight);
            setSize(width, textFieldHeight);
        }

        field.setBounds(0, 0, width, textFieldHeight);
        suggestionsPane.setBounds(0, textFieldHeight, listWidth, listHeight);

    }

    @Override
    public void setBounds(int x, int y, int width, int height) {
        super.setBounds(x, y, width, height);
    }

    /**
     * Montre les suggestions.
     */
    public void showSuggestions() {
        showSuggestions = true;
        computeSuggestions();
                
        panel.setSize(Math.max(width, listWidth), textFieldHeight + Math.min(suggestionsPane.getHeight(), listHeight));
        setSize(Math.max(width, listWidth), textFieldHeight + Math.min(suggestionsPane.getHeight(), listHeight));
        
    }

    /**
     * Cache les suggestions.
     */
    public void hideSuggestions() {
        showSuggestions = false;
        panel.setSize(width, textFieldHeight);
        setSize(width, textFieldHeight);
    }

    /**
     * Renvoie le texte.
     * @return le texte.
     */
    public String getText() {
        if (field.getText() == null) {
            return null;
        } else {
            return field.getText();
        }
    }

    /**
     * Définit le texte.
     * @param text le texte.
     */
    public void setText(String text) {
        field.setText(text);
    }

    @Override
    public void setEnabled(boolean enabled) {
        hideSuggestions();
        field.setEditable(enabled);
    }
}
