/*
 * FieldEditor.java
 *
 * Created on February 6, 2007, 3:16 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package usda.weru.erosion.barriereditor;

import com.klg.jclass.cell.JCCellEditorEvent;
import com.klg.jclass.cell.JCCellInfo;
import com.klg.jclass.cell.editors.JCComboBoxCellEditor;
import com.klg.jclass.cell.editors.JCDoubleCellEditor;
import com.klg.jclass.cell.renderers.JCComboBoxCellRenderer;
import com.klg.jclass.table.JCCellRange;
import com.klg.jclass.table.JCCellStyle;
import com.klg.jclass.table.JCSelectEvent;
import com.klg.jclass.table.JCSelectListener;
import com.klg.jclass.table.JCTableEnum;
import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import de.schlichtherle.truezip.file.TFile;
import java.util.Collection;
import javax.swing.ComboBoxModel;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.border.BevelBorder;
import usda.weru.erosion.DataStore;
import usda.weru.erosion.barriereditor.gui.FieldEditor_n;
import usda.weru.util.table.WepsTableMeta;

/**
 *
 * @author Joseph Levin
 */
public class FieldEditor extends FieldEditor_n implements PropertyChangeListener, JCSelectListener {

    private static final long serialVersionUID = 1L;

    protected FieldDataModel c_model;
    protected boolean c_blockedSelection = false;

    /** Creates a new instance of FieldEditor */
    public FieldEditor() {

        c_model = new FieldDataModel();

        g_fieldPanel.setFieldDataModel(c_model);
        TFile file = new TFile("tables/barrier.xml");
        WepsTableMeta meta = new WepsTableMeta();
        meta.fromFile(file);
        g_barrierTable.getDefaultCellStyle().setHorizontalAlignment(JCTableEnum.RIGHT);
        g_barrierTable.addSelectListener(this);
        g_barrierTable.setMeta(meta);
        g_barrierTable.setBorder(new BevelBorder(BevelBorder.LOWERED));
        g_barrierTable.setDataSource(c_model);
        g_barrierTable.setSelectionPolicy(JCTableEnum.SELECT_RANGE);
        g_barrierTable.setCellEditor(Double.class, new DoubleCellEditor());
        g_barrierTable.setAllowCellResize(JCTableEnum.RESIZE_COLUMN);
        g_barrierTable.setPixelHeight(JCTableEnum.ALL, 20);

        JCCellStyle typeStyle = new JCCellStyle(g_barrierTable.getDefaultCellStyle());
        typeStyle.setCellEditor(new BarrierTypeCellEditor());
        typeStyle.setCellRenderer(new BarrierTypeCellRenderer<>());
        typeStyle.setEditable(true);
        typeStyle.setHorizontalAlignment(JCTableEnum.LEFT);
        g_barrierTable.setCellStyle(new JCCellRange(JCTableEnum.ALL, 1, JCTableEnum.ALL, 1), typeStyle);

        //So we can listen for barriers being selected.
        g_fieldPanel.addPropertyChangeListener(this);

    }

    public boolean checkBarriers() {
        for (int b = 0; b < c_model.getBarrierCount(); b++) {
            BarrierPolygon barrier = c_model.getBarrier(b);
            double test = barrier.getX1();
            if (barrier.getY1() == test && barrier.getX2() == test && barrier.getY2() == test) {
                JOptionPane.showMessageDialog(this, "Barrier '" + barrier.getName()
                        + "' has a length of 0 meters\nPlease correct.", "Barrier Error", JOptionPane.ERROR_MESSAGE);
                return false;
            }
        }
        return true;
    }

    protected int tableRowToModel(int row) {
        int headerCount = g_barrierTable.getMeta().getLabelRowCount();
        headerCount--;
        return row - headerCount;
    }

    protected int modelRowToTable(int row) {
        int headerCount = g_barrierTable.getMeta().getLabelRowCount();
        headerCount--;
        return row + headerCount;

    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        String property = evt.getPropertyName();

        if (property.equals(DataStore.SimField)) {
            c_model.setFieldPolygon((FieldPolygon) evt.getNewValue());
            g_yLengthField.setText(c_model.getFieldPolygon().getWidStr());
            g_xLengthField.setText(c_model.getFieldPolygon().getLenStr());
        } else if (property.equals(DataStore.SimRegAngle)) {
            c_model.setFieldAngle(evt.getNewValue().toString());
            g_angleField.setText(Double.toString(c_model.getFieldAngle()));
        } else if (property.startsWith(DataStore.BarriersObj)) {
            String barrierName = property.substring(DataStore.BarriersObj.length() + 1);
            if (evt.getNewValue() != null) {
                BarrierPolygon barrier = (BarrierPolygon) evt.getNewValue();
                //Add or update
                c_model.updateBarrier(barrierName, barrier);

            } else {
                //remove
                c_model.removeBarrier(barrierName);
            }
        } else if (property.equals(FieldPanel.SELECTED_BARRIER_CHANGED_PROPERTY)) {
            BarrierPolygon barrier = (BarrierPolygon) evt.getNewValue();
            g_barrierTable.clearSelectedCells();
            if (barrier == null) {
                return;
            }
            for (int r = 0; r < c_model.getBarrierCount(); r++) {
                if (barrier == c_model.getBarrier(r)) {
                    g_barrierTable.commitEdit(true);
                    g_barrierTable.setRowSelection(modelRowToTable(r), modelRowToTable(r));
                    return;
                }
            }
        }
    }

    @Override
    public void addPropertyChangeListener(PropertyChangeListener listener) {
        super.addPropertyChangeListener(listener);
        c_model.addPropertyChangeListener(listener);
    }

    @Override
    public void removePropertyChangeListener(PropertyChangeListener listener) {
        super.removePropertyChangeListener(listener);
        c_model.removePropertyChangeListener(listener);
    }

    @Override
    protected void addBarrierButtonActionPerformed(java.awt.event.ActionEvent evt) {
        String name = javax.swing.JOptionPane.showInputDialog(this, "Enter barrier name");
        if (name == null || name.trim().length() == 0) {
            return;
        }
        name = name.trim();
        String tempName = name;
        int i = 1;
        while (c_model.containsBarrier(tempName)) {
            tempName = name + "_" + Integer.toString(i);
            i++;
        }
        name = tempName;

        c_model.addBarrier(name);

        g_addBarrierButton.requestFocusInWindow();
    }

    @Override
    protected void angleFieldFocusLost(java.awt.event.FocusEvent evt) {
        angleFieldActionPerformed(null);
    }

    @Override
    protected void xLengthFieldFocusLost(java.awt.event.FocusEvent evt) {
        xLengthFieldActionPerformed(null);
    }

    @Override
    protected void xLengthFieldActionPerformed(java.awt.event.ActionEvent evt) {
        c_model.setFieldLength(g_xLengthField.getText());
    }

    @Override
    protected void yLengthFieldFocusLost(java.awt.event.FocusEvent evt) {
        yLengthFieldActionPerformed(null);
    }

    @Override
    protected void yLengthFieldActionPerformed(java.awt.event.ActionEvent evt) {
        c_model.setFieldWidth(g_yLengthField.getText());
    }

    @Override
    protected void angleFieldActionPerformed(java.awt.event.ActionEvent evt) {
        c_model.setFieldAngle(g_angleField.getText());
    }

    @Override
    public void beforeSelect(JCSelectEvent e) {
    }

    @Override
    public void select(JCSelectEvent e) {
    }

    @Override
    public void afterSelect(JCSelectEvent e) {
    }

    public static void main(String[] args) {
        FieldEditor fer = new FieldEditor();
        JFrame demoFrame;
        demoFrame = new JFrame("Testing Field Editor");
        demoFrame.setContentPane(fer);
        demoFrame.pack();
        demoFrame.setVisible(true);

    }

    public void keyTyped(KeyEvent e) {
    }

    public void keyPressed(KeyEvent e) {
    }

    @Override
    protected void removeBarrierButtonActionPerformed(java.awt.event.ActionEvent evt) {
        // Despite not technically being enforced, getSelectedCells()
        // will always return a collection of JCCellRanges.
        @SuppressWarnings("unchecked")
        Collection<JCCellRange> selectedCells = (Collection<JCCellRange>) g_barrierTable.getSelectedCells();
        if (selectedCells == null) {
            return;
        }
        /*
         Collection<JCCellRange> selectedCells = null;
         Object o = g_barrierTable.getSelectedCells();
         if (o != null) {
         selectedCells = (Collection<JCCellRange>) o;
         } else {
         return;
         }
         * */
        for (JCCellRange range : selectedCells) {
            if (range.start_row > range.end_row) {
                range.start_row = range.end_row;
                //range.end_row = range.start_row;
            }
            if (range.end_row > c_model.getNumRows()) {
                range.end_row = c_model.getNumRows();
            }

            for (int r = range.start_row; r <= range.end_row; r++) {
                BarrierPolygon barrier = c_model.getBarrier(tableRowToModel(r));
                if (barrier != null) {
                    c_model.removeBarrier(barrier.getName());
                }
            }
        }
    }

    /**
     *
     */
    public void commitEdits() {
        g_barrierTable.commitEdit(true);
    }

    @SuppressWarnings("unchecked") // Quest's fault again
    class BarrierTypeCellRenderer<E> extends JCComboBoxCellRenderer {

        private static final long serialVersionUID = 1L;

        public BarrierTypeCellRenderer() {
            setModel((ComboBoxModel<E>) c_model.getBarrierTypeModel());
        }

        @Override
        public Component getRendererComponent(JCCellInfo info, Object o, boolean selected) {
            getModel().setSelectedItem(o);
            return super.getRendererComponent(info, o, selected);
        }
    }

    @SuppressWarnings("unchecked") // Quest's fault
    class BarrierTypeCellEditor extends JCComboBoxCellEditor implements ItemListener, FocusListener {

        private static final long serialVersionUID = 1L;

        /** Creates a new instance of BarrierTypeCellEditor */
        public BarrierTypeCellEditor() {
            addItemListener(this);
            addFocusListener(this);
            setModel(c_model.getBarrierTypeModel());
        }

        @Override
        public void initialize(AWTEvent ev, JCCellInfo info, Object o) {
            super.initialize(ev, info, o);
            getModel().setSelectedItem(o);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            super.actionPerformed(e);
            support.fireStopEditing(new JCCellEditorEvent(e));
        }

        @Override
        public void itemStateChanged(ItemEvent e) {
            support.fireStopEditing(new JCCellEditorEvent(e));
        }

        @Override
        public void focusGained(FocusEvent e) {
            try {
                showPopup();
            } catch (Exception ex) {
            }
        }

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

    class DoubleCellEditor extends JCDoubleCellEditor implements ActionListener {

        private static final long serialVersionUID = 1L;

        /**
         * Creates a new instance of DoubleCellEditor
         */
        public DoubleCellEditor() {
            addActionListener(this);
        }

        @Override
        public void initialize(AWTEvent ev, JCCellInfo info, Object o) {
            super.initialize(ev, info, o);
            setHorizontalAlignment(info.getHorizontalAlignment());
        }

        @Override
        public void focusGained(FocusEvent event) {
            super.focusGained(event);
            if (!c_blockedSelection) {
                selectAll();
            }
            c_blockedSelection = false;

        }

        @Override
        public void focusLost(FocusEvent event) {
            super.focusLost(event);
            select(0, 0);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            support.fireStopEditing(new JCCellEditorEvent(e));

        }

        @Override
        public void processKeyEvent(KeyEvent e) {

            if (e.getKeyChar() != KeyEvent.CHAR_UNDEFINED && !hasFocus()) {
                c_blockedSelection = true;
                setText(Character.toString(e.getKeyChar()));
            } else {
                super.processKeyEvent(e);
            }

        }
    }
}
