package com.dlsc.flexgantt.showcase.demo.spreadsheet;

import java.awt.Color;
import java.awt.Component;

import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;

import com.dlsc.flexgantt.model.ITimeSpan;
import com.dlsc.flexgantt.model.gantt.ISpreadsheet;
import com.dlsc.flexgantt.swing.AbstractGanttChart;
import com.dlsc.flexgantt.swing.layer.system.DefaultSpreadsheetCellEditor;
import com.dlsc.flexgantt.swing.layer.system.ISpreadsheetCellEditor;
import com.dlsc.flexgantt.swing.layer.system.SpreadsheetLayer;
import com.dlsc.flexgantt.util.INamedObject;

public class SpreadsheetValuesEditor extends DefaultSpreadsheetCellEditor
        implements ISpreadsheetCellEditor {

    private AbstractGanttChart ganttChart;

    public SpreadsheetValuesEditor(AbstractGanttChart gc) {
        super(new JComboBox(new DefaultComboBoxModel()));

        this.ganttChart = gc;
    }

    /*
     * Updates the combo box data model by looking at the given object, which is
     * an enumeration value, finding out the enum to which the value belongs,
     * retrieving the other values of the same enum.
     */
    private void updateComboBox(Object value) {
        Enum e = (Enum) value;

        Class cl = null;
        if (e != null) {
            cl = e.getDeclaringClass();
        }

        if (cl == null) {
            ISpreadsheet spreadsheet = ganttChart.getActiveSpreadsheet();
            cl = spreadsheet.getDefaultValueType();
        }

        Object[] obj = cl.getEnumConstants();
        JComboBox box = (JComboBox) getComponent();
        box.setMaximumRowCount(obj.length);
        box.setRenderer(new SpreadsheetValuesListCellRenderer());
        DefaultComboBoxModel spreadsheetModel = (DefaultComboBoxModel) box
                .getModel();
        spreadsheetModel.removeAllElements();
        for (Object o : obj) {
            spreadsheetModel.addElement(o);
        }
    }

    /**
     * A renderer for the enum editor combo box (drop down list). We want to be
     * able to display human readable names and not enum values. The renderer
     * will do so by checking whether the enum value implements the
     * {@link INamedObject} interface. If it does it will call the method
     * {@link INamedObject#getName()}.
     */
    class SpreadsheetValuesListCellRenderer extends DefaultListCellRenderer {

        /*
         * (non-Javadoc)
         * 
         * @see javax.swing.DefaultListCellRenderer#getListCellRendererComponent
         * (javax.swing.JList, Object, int, boolean, boolean)
         */

        @Override
        public Component getListCellRendererComponent(JList list, Object value,
                int index, boolean isSelected, boolean cellHasFocus) {
            JLabel label = (JLabel) super.getListCellRendererComponent(list,
                    value, index, isSelected, cellHasFocus);
            if (value instanceof SpreadsheetValues) {

                SpreadsheetValues sv = (SpreadsheetValues) value;

                switch (sv) {
                case ZERO:
                    setText("Unused");
                    break;
                case TEN:
                    setText("10");
                    break;
                case TWENTY:
                    setText("20");
                    break;
                case THIRTY:
                    setText("30");
                    break;
                case FOURTY:
                    setText("40");
                    break;
                case FIFTY:
                    setText("50");
                    break;
                case SIXTY:
                    setText("60");
                    break;
                case SEVENTY:
                    setText("70");
                    break;
                case EIGHTY:
                    setText("80");
                    break;
                case NINETY:
                    setText("90");
                    break;
                case HUNDRED:
                    setText("100");
                    break;
                case BROKEN:
                    setText("Broken Machine");
                    break;
                default:
                    setText("");
                    break;
                }
                setOpaque(true);
                Color c = sv.getColor();

                /*
                 * Modify color, make it transparent. This way background
                 * textures (e.g. weekends) will still be visible.
                 */
                setBackground(new Color(c.getRed(), c.getGreen(), c.getBlue(),
                        100));

                if (isSelected) {
                    setForeground(Color.RED);
                }
            }

            return label;
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see DefaultSpreadsheetCellEditor#getSpreadsheetCellEditorComponent(
     * SpreadsheetLayer, Object, int, ITimeSpan)
     */

    @Override
    public Component getSpreadsheetCellEditorComponent(
            SpreadsheetLayer spreadsheet, Object value, int row, ITimeSpan span) {
        updateComboBox(value);
        return super.getSpreadsheetCellEditorComponent(spreadsheet, value, row,
                span);
    }
}