/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * SiteChooser.java
 *
 * Created on Sep 22, 2009, 5:02:41 PM
 */

package usda.weru.weps.location.chooser;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.beans.Beans;
import java.util.Arrays;
import java.util.LinkedList;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListCellRenderer;
import org.apache.log4j.Logger;
import usda.weru.util.WepsComboBox;
import usda.weru.weps.location.Site;

/**
 *
 * @author Joseph Levin <joelevin@weru.ksu.edu>
 */
public class SiteChooser extends javax.swing.JPanel {
    private static final Logger LOGGER = Logger.getLogger(SiteChooser.class);

    public static final String PROP_ROOT_SITE = "rootSite";
    public static final String PROP_SELECTED_SITE = "selectedSite";

    private Site c_rootSite;
    private ChainedComboBox c_rootComboBox;

    private Site c_selectedSite;
    

    /** Creates new form SiteChooser */
    public SiteChooser() {
        initComponents();
        

        c_rootComboBox = new ChainedComboBox();
        add(c_rootComboBox);
        //c_rootComboBox.setEnabled(false);

        if(!Beans.isDesignTime()){
            setRootSite(null);
        }

    }

    @Override
    public Dimension getPreferredSize() {
        Dimension temp = super.getPreferredSize();
        return new Dimension(0, temp.height);

    }

    @Override
    public Dimension getMinimumSize() {
        Dimension temp = super.getMinimumSize();
        return new Dimension(0, temp.height);
    }





    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        labelPanel = new javax.swing.JPanel();

        labelPanel.setLayout(new java.awt.GridLayout(0, 1));

        setFont(getFont().deriveFont(getFont().getStyle() & ~java.awt.Font.BOLD));
        setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.Y_AXIS));
    }// </editor-fold>//GEN-END:initComponents

    public void setRootSite(Site root){        
        Site old = c_rootSite;

        c_rootSite = root;

        //TODO: update the display choices
        c_rootComboBox.setModel(new SiteComboBoxModel(getChildren(root)));
        c_rootComboBox.setSelectedIndex(-1);

        firePropertyChange(PROP_ROOT_SITE, old, c_rootSite);
    }

    public Site getRootSite(){
        return c_rootSite;
    }

    public void setSelectedSite(Site site){
        
        try{

            if(site == null){
                c_rootComboBox.setSelectedIndex(-1);
                return;
            }

            LinkedList <Site> chain = new LinkedList<Site>();
            //need to build the chain from the site
            Site temp = site;
            while(temp != null){
                if(temp.equals(c_rootSite)){
                    //don't go above the root site
                    break;
                }
                chain.add(0, temp);
                temp = temp.getParent();
            }

            //the top of the chain should be a child of the root site
            if(c_rootSite != null){
                boolean isChild = false;

                for(Site child : c_rootSite.getSubDivisions()){
                    if(child.equals(chain.getFirst())){
                        isChild = true;
                        break;
                    }
                }

                if(!isChild){
                    LOGGER.warn("Unable to set site choice. " + chain.getFirst().getDisplayName() + " is not a division of " + c_rootSite.getDisplayName());
                    c_rootComboBox.setSelectedIndex(-1);
                    return;
                }
            }

            ChainedComboBox combo = c_rootComboBox;

            for (Site choice : chain){
                combo.setSelectedItem(choice);

                combo = combo.c_downStream;
            }

            if(combo != null){
                combo.setSelectedItem(null);
            }



           
        }
        finally{
            setSelectedSite2(site);
        }


        
    }

    private void setSelectedSite2(Site site){
        Site old = c_selectedSite;

        c_selectedSite = site;
        firePropertyChange(PROP_SELECTED_SITE, old, c_selectedSite);
    }

    public Site getSelectedSite(){
        return c_selectedSite;
    }

    private Site[] getChildren(Site site){
        Site[] children;
        if(site != null){
            children = site.getSubDivisions();
        }
        else{
            children = Site.countries();
        }

        Arrays.sort(children);

        return children;
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel labelPanel;
    // End of variables declaration//GEN-END:variables


    private class ChainedComboBox extends WepsComboBox implements ItemListener{
        
        private ChainedComboBox c_downStream;
        private JLabel c_label;

        public ChainedComboBox(){            
            initilize();
        }

        private void initilize(){
            //create and add label
            c_label = new JLabel("Site");
            labelPanel.add(c_label);
            
            setFont(getFont().deriveFont(Font.PLAIN));
            addItemListener(this);
            setRenderer(getRendererInstance());

        }

        @Override
        public void itemStateChanged(ItemEvent e) {
            //create the down stream
            Site selected = getSelectedSite();
            Site[] children = selected != null ? getChildren(selected) : null;
            if(children != null && children.length > 0){
                if(c_downStream == null){
                    addDownStream();
                }

                c_downStream.setModel(new SiteComboBoxModel(children));                
                if(children.length == 1){
                    c_downStream.setSelectedIndex(0);
                }
                else{
                    c_downStream.setSelectedIndex(-1);
                }
                
            }
            else{
                removeDownstream();
            }

            setSelectedSite2(selected);
            

        }

        @Override
        public void setModel(ComboBoxModel aModel) {
            super.setModel(aModel);
            updateLabel();
        }



        private void addDownStream(){
            c_downStream = new ChainedComboBox();          
            SiteChooser.this.add(c_downStream);
        }


        public void removeDownstream(){
            if(c_downStream != null){
                c_downStream.removeDownstream();

                //remove the label
                labelPanel.remove(c_downStream.c_label);

                SiteChooser.this.remove(c_downStream);
                c_downStream = null;
                
            }

        }

        private void updateLabel(){
            try{
                if(c_label == null){
                    return;
                }
                Object o = getModel().getSize() > 0 ? getModel().getElementAt(0) : null;

                Site firstSiteInModel = null;
                if(o instanceof Site){
                    firstSiteInModel = (Site) o;
                }


                String designation = firstSiteInModel != null ? firstSiteInModel.getDesgination().name() : "Site";
                c_label.setText(designation + ":" );
            }
            catch(Exception e){
                LOGGER.warn("Unable to determine site label.", e);
            }
        }

        public Site getSelectedSite(){
            if(getSelectedItem() instanceof Site){
                return (Site) getSelectedItem();
            }
            else{
                return null;
            }
        }




    }

    private class SiteComboBoxModel extends DefaultComboBoxModel{        

        public SiteComboBoxModel(Site[] sites) {
            super(sites);
        }

    }

    private InternalCellRenderer c_renderer;
    private synchronized InternalCellRenderer getRendererInstance(){
            if(c_renderer == null){
                c_renderer = new InternalCellRenderer();
            }
            return c_renderer;
        }

    private class InternalCellRenderer extends JLabel implements ListCellRenderer{

        public InternalCellRenderer(){
            setOpaque(true);
        }

        @Override
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            setBackground(isSelected ? list.getSelectionBackground() : list.getBackground());
            setForeground(isSelected ? list.getSelectionForeground(): list.getForeground());


            if (value instanceof Site){
                Site site = (Site) value;
                setText(" " + site.getDisplayName().toUpperCase());
            }
            else{
                setText("");
            }
            
            return this;

            
        }


    }

    public JPanel getLabelPanel(){        
        return labelPanel;

    }

}
