/*
 *  Draco Econometrics
 *  Copyright (C) 2006-2007 Approximatrix, LLC
 *  http://www.approximatrix.com
 *  
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.approximatrix.draco.io.ui;

import java.util.ArrayList;
import java.awt.BorderLayout;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JDialog;
import javax.swing.JRadioButton;
import javax.swing.BoxLayout;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.ButtonGroup;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JComboBox;
import javax.swing.JTextField;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.DefaultCellEditor;
import javax.swing.JOptionPane;
import java.awt.Component;

import java.awt.event.ItemListener;
import java.awt.event.ItemEvent;


import com.approximatrix.draco.application.ApplicationManager;
import com.approximatrix.draco.datamodel.StatTableModel;
import com.approximatrix.draco.io.ImportExport;
import com.approximatrix.draco.io.PastedData;

public class PasteDialog extends JDialog implements ItemListener {

	private static final String IGNORE_MAP_CHOICE = "Do Not Paste";
	
	private JPanel jContentPane = null;
	private JPanel jPanel = null;
	private JRadioButton jNewColumnsRadioButton = null;
	private JRadioButton jNewWSRadioButton = null;
	private JRadioButton jSelectedRowRadioButton = null;
	private JRadioButton jAppendRadioButton = null;
	private JPanel jPanel1 = null;
	private JPanel jPanel2 = null;
	private JRadioButton jInsertRadioButton = null;
	private JRadioButton jOverwriteRadioButton = null;
	private JPanel jPanel3 = null;
	private JPanel jPanel4 = null;
	private JButton jPasteButton = null;
	private JButton jCancelButton = null;
	
	private ButtonGroup position_group = null;  //  @jve:decl-index=0:
	private ButtonGroup technique_group = null;
	private JScrollPane jScrollPane = null;
	private JTable jMappingTable = null;
	
	private StatTableModel model = null;
	private PastedData new_data = null;
	
	private int main_selected_row = -1;
	
	/**
	 * This is the default constructor
	 */
	public PasteDialog(JFrame parent, StatTableModel model, String pasted, int selected_row) {
		super(parent,true);
		initialize();
		this.setLocationRelativeTo(parent);
		
		main_selected_row = selected_row;
		if(main_selected_row == -1) {
			getJSelectedRowRadioButton().setEnabled(false);
		}
		
		new_data = new PastedData(pasted);
		this.model = model;
		
		DefaultTableModel mapmodel = (DefaultTableModel)getJMappingTable().getModel();
	    
	    // Add some columns
		mapmodel.addColumn("Pasted Data", new_data.getHeaders());
		mapmodel.addColumn("Existing Data", new Object[]{"item2"});
		TableColumn col = getJMappingTable().getColumnModel().getColumn(1);
		
		String[] columns = new String[this.model.getColumnCount()+1];
	    columns[0] = IGNORE_MAP_CHOICE;
	    for(int i=0;i<this.model.getColumnCount();i++)
	    	columns[i+1] = this.model.getColumnName(i);
		
	    col.setCellEditor(new ComboBoxEditor(columns));
	    
	    col.setCellRenderer(new ComboBoxRenderer(columns));
	    
	    // Set choices to Ignore
	    for(int i=0;i<getJMappingTable().getRowCount();i++)
	    	getJMappingTable().setValueAt(IGNORE_MAP_CHOICE,i,1);
	    
	    this.itemStateChanged(null);
	}

	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		this.setSize(326, 344);
		this.setTitle("Paste from Clipboard");
		this.setContentPane(getJContentPane());
		
		position_group = new ButtonGroup();
		position_group.add(this.getJAppendRadioButton());
		position_group.add(this.getJNewColumnsRadioButton());
		position_group.add(this.getJSelectedRowRadioButton());
		position_group.add(this.getJNewWSRadioButton());
		
		technique_group = new ButtonGroup();
		technique_group.add(this.getJInsertRadioButton());
		technique_group.add(this.getJOverwriteRadioButton());
		
		this.getJAppendRadioButton().setSelected(true);
		this.getJInsertRadioButton().setSelected(true);
	}

	/**
	 * This method initializes jContentPane
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(new BorderLayout());
			jContentPane.add(getJPanel1(), java.awt.BorderLayout.NORTH);
			jContentPane.add(getJPanel3(), java.awt.BorderLayout.CENTER);
			jContentPane.add(getJPanel4(), java.awt.BorderLayout.SOUTH);
		}
		return jContentPane;
	}

	/**
	 * This method initializes jPanel	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getJPanel() {
		if (jPanel == null) {
			jPanel = new JPanel();
			jPanel.setLayout(new BoxLayout(getJPanel(), BoxLayout.Y_AXIS));
			jPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Paste Position", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, null, null));
			jPanel.add(getJNewColumnsRadioButton(), null);
			jPanel.add(getJNewWSRadioButton(), null);
			jPanel.add(getJSelectedRowRadioButton(), null);
			jPanel.add(getJAppendRadioButton(), null);
		}
		return jPanel;
	}

	/**
	 * This method initializes jNewColumnsRadioButton	
	 * 	
	 * @return javax.swing.JRadioButton	
	 */
	private JRadioButton getJNewColumnsRadioButton() {
		if (jNewColumnsRadioButton == null) {
			jNewColumnsRadioButton = new JRadioButton();
			jNewColumnsRadioButton.setText("As New Columns");
			jNewColumnsRadioButton.addItemListener(this);
		}
		return jNewColumnsRadioButton;
	}

	/**
	 * This method initializes jNewColumnsRadioButton	
	 * 	
	 * @return javax.swing.JRadioButton	
	 */
	private JRadioButton getJNewWSRadioButton() {
		if (jNewWSRadioButton == null) {
			jNewWSRadioButton = new JRadioButton();
			jNewWSRadioButton.setText("As New Worksheet");
			jNewWSRadioButton.addItemListener(this);
		}
		return jNewWSRadioButton;
	}
	
	/**
	 * This method initializes jSelectedRowRadioButton	
	 * 	
	 * @return javax.swing.JRadioButton	
	 */
	private JRadioButton getJSelectedRowRadioButton() {
		if (jSelectedRowRadioButton == null) {
			jSelectedRowRadioButton = new JRadioButton();
			jSelectedRowRadioButton.setText("At Selected Row");
			jSelectedRowRadioButton.addItemListener(this);
		}
		return jSelectedRowRadioButton;
	}

	/**
	 * This method initializes jAppendRadioButton	
	 * 	
	 * @return javax.swing.JRadioButton	
	 */
	private JRadioButton getJAppendRadioButton() {
		if (jAppendRadioButton == null) {
			jAppendRadioButton = new JRadioButton();
			jAppendRadioButton.setText("Append to Data Set");
			jAppendRadioButton.addItemListener(this);
		}
		return jAppendRadioButton;
	}

	/**
	 * This method initializes jPanel1	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getJPanel1() {
		if (jPanel1 == null) {
			jPanel1 = new JPanel();
			jPanel1.setLayout(new BorderLayout());
			jPanel1.add(getJPanel(), java.awt.BorderLayout.NORTH);
			jPanel1.add(getJPanel2(), java.awt.BorderLayout.CENTER);
		}
		return jPanel1;
	}

	/**
	 * This method initializes jPanel2	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getJPanel2() {
		if (jPanel2 == null) {
			jPanel2 = new JPanel();
			jPanel2.setLayout(new BoxLayout(getJPanel2(), BoxLayout.Y_AXIS));
			jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Paste Technique", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, null, null));
			jPanel2.add(getJInsertRadioButton(), null);
			jPanel2.add(getJOverwriteRadioButton(), null);
		}
		return jPanel2;
	}

	/**
	 * This method initializes jInsertRadioButton	
	 * 	
	 * @return javax.swing.JRadioButton	
	 */
	private JRadioButton getJInsertRadioButton() {
		if (jInsertRadioButton == null) {
			jInsertRadioButton = new JRadioButton();
			jInsertRadioButton.setText("Insert into Data Set");
			jInsertRadioButton.addItemListener(this);			
		}
		return jInsertRadioButton;
	}

	/**
	 * This method initializes jOverwriteRadioButton	
	 * 	
	 * @return javax.swing.JRadioButton	
	 */
	private JRadioButton getJOverwriteRadioButton() {
		if (jOverwriteRadioButton == null) {
			jOverwriteRadioButton = new JRadioButton();
			jOverwriteRadioButton.setText("Overwrite Existing Data");
			jOverwriteRadioButton.addItemListener(this);
		}
		return jOverwriteRadioButton;
	}

	/**
	 * This method initializes jPanel3	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getJPanel3() {
		if (jPanel3 == null) {
			jPanel3 = new JPanel();
			jPanel3.setLayout(new BorderLayout());
			jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Variable Mapping", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, null, null));
			jPanel3.add(getJScrollPane(), java.awt.BorderLayout.CENTER);
		}
		return jPanel3;
	}

	/**
	 * This method initializes jPanel4	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getJPanel4() {
		if (jPanel4 == null) {
			FlowLayout flowLayout = new FlowLayout();
			flowLayout.setAlignment(java.awt.FlowLayout.RIGHT);
			jPanel4 = new JPanel();
			jPanel4.setLayout(flowLayout);
			jPanel4.add(getJPasteButton(), null);
			jPanel4.add(getJCancelButton(), null);
		}
		return jPanel4;
	}

	/**
	 * This method initializes jPasteButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getJPasteButton() {
		if (jPasteButton == null) {
			jPasteButton = new JButton();
			jPasteButton.setText("Paste");
			jPasteButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					boolean return_val = false;
					boolean requireDataUpdate = true;
					if(getJNewColumnsRadioButton().isSelected()) {
						return_val = pasteNewColumns();
					} else if(getJNewWSRadioButton().isSelected()) {
						return_val = pasteNewWs();
						requireDataUpdate = false;
					} else if(getJAppendRadioButton().isSelected()) {
						return_val = pasteAppend();
					} else if(getJSelectedRowRadioButton().isSelected()) {
						if(getJOverwriteRadioButton().isSelected()) {
							return_val = pasteOverwrite();
						} else {
							return_val = pasteInsert();
						}
					} else {
						System.out.println("Not implemented...");
					}
					if(return_val && requireDataUpdate) {
						model.fireTableDataChanged();
						model.fireTableStructureChanged();
					}
					dispose();
				}
			});
		}
		return jPasteButton;
	}

	/**
	 * This method initializes jCancelButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getJCancelButton() {
		if (jCancelButton == null) {
			jCancelButton = new JButton();
			jCancelButton.setText("Cancel");
			jCancelButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					dispose();
				}
			});
		}
		return jCancelButton;
	}

	/**
	 * This method initializes jScrollPane	
	 * 	
	 * @return javax.swing.JScrollPane	
	 */
	private JScrollPane getJScrollPane() {
		if (jScrollPane == null) {
			jScrollPane = new JScrollPane();
			jScrollPane.setViewportView(getJMappingTable());
		}
		return jScrollPane;
	}

	/**
	 * This method initializes jMappingTable	
	 * 	
	 * @return javax.swing.JTable	
	 */
	private JTable getJMappingTable() {
		if (jMappingTable == null) {
			jMappingTable = new JTable();
		}
		return jMappingTable;
	}

	private class ComboBoxRenderer extends JComboBox implements TableCellRenderer {
        public ComboBoxRenderer(String[] items) {
            super(items);
        }
    
        public Component getTableCellRendererComponent(JTable table, Object value,
                boolean isSelected, boolean hasFocus, int row, int column) {
            if (isSelected) {
                setForeground(table.getSelectionForeground());
                super.setBackground(table.getSelectionBackground());
            } else {
                setForeground(table.getForeground());
                setBackground(table.getBackground());
            }
    
            // Select the current value
            setSelectedItem(value);
            return this;
        }
    }
	
	private class ComboBoxEditor extends DefaultCellEditor {
        public ComboBoxEditor(String[] items) {
            super(new JComboBox(items));
        }
    }
	
	public void itemStateChanged(ItemEvent ie) {
		if(getJNewColumnsRadioButton().isSelected()) {
			getJMappingTable().setEnabled(false);
			getJMappingTable().setVisible(false);
			
			getJInsertRadioButton().setEnabled(false);
			getJOverwriteRadioButton().setEnabled(false);
		} else if(getJNewWSRadioButton().isSelected()) {
			getJMappingTable().setEnabled(false);
			getJMappingTable().setVisible(false);
			
			getJInsertRadioButton().setEnabled(false);
			getJOverwriteRadioButton().setEnabled(false);
		} else if(getJAppendRadioButton().isSelected()) {
			getJMappingTable().setEnabled(true);
			getJMappingTable().setVisible(true);
			
			getJInsertRadioButton().setEnabled(false);
			getJOverwriteRadioButton().setEnabled(false);
			
		} else {
			getJMappingTable().setEnabled(true);
			getJMappingTable().setVisible(true);
			
			getJInsertRadioButton().setEnabled(true);
			getJOverwriteRadioButton().setEnabled(true);
		}
	}
	
	private boolean pasteNewWs() {
		StatTableModel local_model = ImportExport.CreatePanelModel(new_data.getData(), new_data.getHeaders());
		ApplicationManager.RequestAndReturnNewWindow(local_model).toFront();
		return true;
	}
	
	private boolean pasteNewColumns() {
		StatTableModel local_model = ImportExport.CreatePanelModel(new_data.getData(), new_data.getHeaders());
		if(local_model.getRowCount() == model.getRowCount()) {
			for(int i=0;i<local_model.getColumnCount();i++) {
				model.addColumn(local_model.getColumn(i), local_model.getColumnName(i));
			}
		} else {
			Object[] message = new Object[2];
			message[0] = new String("Please select row offset to paste data");
			message[1] = new String("(0 for first row):");
			String response = JOptionPane.showInputDialog(this,message,ApplicationManager.APP_NAME,JOptionPane.QUESTION_MESSAGE);
			int row_start = 0;
			try {
				row_start = new Integer(response).intValue();
			} catch(NumberFormatException nfe) {
				return false;
			}
			
			for(int i=0;i<local_model.getColumnCount();i++) {
				Object[] add_column = new Object[model.getRowCount()];
				Object[] new_column = local_model.getColumn(i);
				int new_j = 0;
				for(int orig_j=0;orig_j<model.getRowCount();orig_j++) {
					if(orig_j >= row_start && new_j < local_model.getRowCount()) {
						add_column[orig_j] = new_column[new_j];
						new_j++;
					} else {
						add_column[orig_j] = null;
					}
				}
				model.addColumn(add_column, local_model.getColumnName(i));
			}
		}
		
		return true;
	}
	
	private ArrayList getMappingPairs() {
		ArrayList pairs = new ArrayList();
		for(int i=0;i<getJMappingTable().getRowCount();i++) {
			if(IGNORE_MAP_CHOICE.compareTo((String)getJMappingTable().getValueAt(i,1))!=0) {
				String[] one_pair = new String[2];
				one_pair[0] = (String)getJMappingTable().getValueAt(i,0);
				one_pair[1] = (String)getJMappingTable().getValueAt(i,1);
				pairs.add(one_pair);
			}
		}
		return pairs;
	}
	
	private boolean pasteAppend() {
		StatTableModel local_model = ImportExport.CreatePanelModel(new_data.getData(), new_data.getHeaders());
		
		ArrayList pairs = getMappingPairs();
	
		if(pairs.size() > 0) {
			for(int lm_i = 0; lm_i < local_model.getRowCount(); lm_i++) {
				model.addRow();
				int new_row_index = model.getRowCount()-1;
				for(int nv_i = 0; nv_i < pairs.size(); nv_i++) {
					String[] one_pair = (String[])pairs.get(nv_i);
					int old_col = model.getColumnNumber(one_pair[1]);
					int new_col = local_model.getColumnNumber(one_pair[0]);
					
					if(old_col >=0 && new_col >= 0) {
						model.setValueAt(local_model.getValueAt(lm_i, new_col), new_row_index, old_col);
					} else {
						System.err.print("Naming error - Old: "+one_pair[0]+" New: "+one_pair[1]);
					}
				}
			}
		}
		
		return true;
	}
	
	private boolean pasteInsert() {
		StatTableModel local_model = ImportExport.CreatePanelModel(new_data.getData(), new_data.getHeaders());
		ArrayList pairs = getMappingPairs();
		
		if(pairs.size() > 0) {
			for(int lm_i = 0; lm_i < local_model.getRowCount(); lm_i++) {
				model.addRow(main_selected_row);
				int new_row_index = main_selected_row;
				for(int nv_i = 0; nv_i < pairs.size(); nv_i++) {
					String[] one_pair = (String[])pairs.get(nv_i);
					int old_col = model.getColumnNumber(one_pair[1]);
					int new_col = local_model.getColumnNumber(one_pair[0]);
					
					if(old_col >=0 && new_col >= 0) {
						model.setValueAt(local_model.getValueAt(lm_i, new_col), new_row_index, old_col);
					} else {
						System.err.print("Naming error - Old: "+one_pair[0]+" New: "+one_pair[1]);
					}
				}
				main_selected_row++;
			}
		}
		
		return true;
	}
	
	private boolean pasteOverwrite() {
		StatTableModel local_model = ImportExport.CreatePanelModel(new_data.getData(), new_data.getHeaders());
		ArrayList pairs = getMappingPairs();
		
		if(pairs.size() > 0) {
			for(int lm_i = 0; lm_i < local_model.getRowCount() && main_selected_row < model.getRowCount(); lm_i++) {
				int new_row_index = main_selected_row;
				for(int nv_i = 0; nv_i < pairs.size(); nv_i++) {
					String[] one_pair = (String[])pairs.get(nv_i);
					int old_col = model.getColumnNumber(one_pair[1]);
					int new_col = local_model.getColumnNumber(one_pair[0]);
					
					if(old_col >=0 && new_col >= 0) {
						model.setValueAt(local_model.getValueAt(lm_i, new_col), new_row_index, old_col);
					} else {
						System.err.print("Naming error - Old: "+one_pair[0]+" New: "+one_pair[1]);
					}
				}
				main_selected_row++;
			}
		}
		
		return true;
	}
	
}  //  @jve:decl-index=0:visual-constraint="135,11"
