package hiro.yoshioka.ui.multispan;

import hiro.yoshioka.sdh.ResultSetDataHolder;
import hiro.yoshioka.util.CSVUtil;
import hiro.yoshioka.util.StringUtil;

import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.IOException;

import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;

public class ExcelAdapter implements ActionListener {

	private Clipboard system;

	private SimaTable jTable1;

	public ExcelAdapter(SimaTable myJTable) {
		jTable1 = myJTable;
		KeyStroke copy = KeyStroke.getKeyStroke(KeyEvent.VK_C,
				ActionEvent.CTRL_MASK, false);
		// Identifying the copy KeyStroke user can modify this
		// to copy on some other Key combination.
		KeyStroke paste = KeyStroke.getKeyStroke(KeyEvent.VK_V,
				ActionEvent.CTRL_MASK, false);

		KeyStroke del = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0, false);

		// Identifying the Paste KeyStroke user can modify this
		// to copy on some other Key combination.
		jTable1.registerKeyboardAction(this, "Copy", copy,
				JComponent.WHEN_FOCUSED);
		jTable1.registerKeyboardAction(this, "Paste", paste,
				JComponent.WHEN_FOCUSED);
		jTable1.registerKeyboardAction(this, "Del", del,
				JComponent.WHEN_FOCUSED);

		system = Toolkit.getDefaultToolkit().getSystemClipboard();
	}

	public void copyWithHeaer() {
		StringBuilder sbf = new StringBuilder();
		int[] colsselected = jTable1.getSelectedColumns();
		ResultSetDataHolder rdh = jTable1.getResultSetDataHolder();
		for (int j = 0; j < colsselected.length; j++) {
			if (j > 0) {
				sbf.append("\t");
			}
			String val = rdh.getKey()[colsselected[j]];
			if (val.indexOf(StringUtil.LINE_SEPARATOR) >= 0) {
				val = "\"" + val + "\"";
			}
			sbf.append(val);
		}
		sbf.append(StringUtil.LINE_SEPARATOR);
		copy(sbf);
	}

	public void copy() {
		StringBuilder sbf = new StringBuilder();
		copy(sbf);
	}

	private void copy(StringBuilder sbf) {

		int numcols = jTable1.getSelectedColumnCount();
		int numrows = jTable1.getSelectedRowCount();
		int[] rowsselected = jTable1.getSelectedRows();
		int[] colsselected = jTable1.getSelectedColumns();
		if (!((numrows - 1 == rowsselected[rowsselected.length - 1]
				- rowsselected[0] && numrows == rowsselected.length) && (numcols - 1 == colsselected[colsselected.length - 1]
				- colsselected[0] && numcols == colsselected.length))) {
			JOptionPane.showMessageDialog(null, "Invalid Copy Selection",
					"Invalid Copy Selection", JOptionPane.ERROR_MESSAGE);
			return;
		}
		for (int i = 0; i < numrows; i++) {
			for (int j = 0; j < numcols; j++) {
				String val = (String) jTable1.getValueAt(rowsselected[i],
						colsselected[j]);
				if (val.indexOf(StringUtil.LINE_SEPARATOR) >= 0) {
					val = "\"" + val + "\"";
				}
				sbf.append(val);
				if (j < numcols - 1) {
					sbf.append("\t");
				}
			}
			sbf.append(StringUtil.LINE_SEPARATOR);
		}

		ResultSetDataHolder rdh = jTable1.getResultSetDataHolder();

		int xend = colsselected[colsselected.length - 1];
		if (xend <= 0 && colsselected[0] <= 0) {
			return;
		}
		if (colsselected[0] <= 0) {
			colsselected[0] = 1;
		}
		ResultSetDataHolder rdh2 = rdh.createIncetanceByClip(colsselected[0],
				rowsselected[0], xend, rowsselected[rowsselected.length - 1]);
		ExcelTransfer tran = new ExcelTransfer(rdh2, sbf.toString());
		system.setContents(tran, tran);

	}

	public void paseteTo1Cell() {
		if (!((SimaTable) jTable1).getResultSetDataHolder()
				.hasResultSetMetaData()) {
			return;
		}
		int startCol = jTable1.getSelectedColumn();
		int startRow = jTable1.getSelectedRow();
		if (startCol <= 0 || startRow < 0) {
			return;
		}
		try {
			Transferable tran = system.getContents(this);

			String trstring = (String) tran
					.getTransferData(DataFlavor.stringFlavor);
			jTable1.getModel().setValueAt(trstring, startRow, startCol);

		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	public void paste() {

		if (!((SimaTable) jTable1).getResultSetDataHolder()
				.hasResultSetMetaData()) {
			return;
		}
		int startRow = (jTable1.getSelectedRows())[0];
		int startCol = (jTable1.getSelectedColumns())[0];
		System.out.println("startRow=" + startRow + "/startCol=" + startCol);
		try {
			Transferable tran = system.getContents(this);

			if (tran.isDataFlavorSupported(RDHFlavor.rdhFlavor)) {
				ResultSetDataHolder myRdh = (ResultSetDataHolder) tran
						.getTransferData(RDHFlavor.rdhFlavor);

				String[] keys = myRdh.getKey();
				for (int irow = 0; irow < myRdh.getRowCount(); irow++) {
					for (int j = 1; j < keys.length; j++) {
						if (startCol + j - 1 <= 0) {
							continue;
						}
						String val = myRdh.getRow(irow)[j];
						jTable1.getModel().setValueAt(val, startRow + irow,
								startCol + j - 1);
					}
				}

				return;
			}

			String trstring = (String) tran
					.getTransferData(DataFlavor.stringFlavor);
			String[][] datum = CSVUtil.splitByTAB_quoteDouble(trstring);
			for (int i = 0; i < datum.length; i++) {
				for (int j = 0; j < datum[i].length; j++) {
					if (startCol + j <= 0) {
						continue;
					}
					if (startRow + i < jTable1.getRowCount()
							&& startCol + j < jTable1.getColumnCount()) {
						jTable1.setValueAt(datum[i][j], startRow + i, startCol
								+ j);
					}
				}
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	public void actionPerformed(ActionEvent e) {
		if (e.getActionCommand().compareTo("Copy") == 0) {
			copy();
		}

		if (e.getActionCommand().compareTo("Paste") == 0) {
			paste();
		}
		if (e.getActionCommand().compareTo("Del") == 0) {
			if (!((SimaTable) jTable1).getResultSetDataHolder()
					.hasResultSetMetaData()) {
				return;
			}

			try {
				int[] dels = jTable1.getSelectedRows();

				((SimaTable) jTable1).deleteRows(dels);
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}
}

class ExcelTransfer implements Transferable, ClipboardOwner {

	private static final DataFlavor[] flavors = { RDHFlavor.rdhFlavor,
			DataFlavor.stringFlavor };

	private ResultSetDataHolder data;

	private String strdata;

	public ExcelTransfer(ResultSetDataHolder rdh, String str) {
		this.data = rdh;
		this.strdata = str;
	}

	public DataFlavor[] getTransferDataFlavors() {
		return (DataFlavor[]) flavors.clone();
	}

	public boolean isDataFlavorSupported(DataFlavor flavor) {
		for (int i = 0; i < flavors.length; i++) {
			if (flavor.equals(flavors[i])) {
				return true;
			}
		}
		return false;
	}

	public Object getTransferData(DataFlavor flavor)
			throws UnsupportedFlavorException, IOException {
		if (flavor.equals(flavors[0])) {
			return data;
		} else if (flavor.equals(flavors[1])) {
			return strdata;
		} else {
			throw new UnsupportedFlavorException(flavor);
		}
	}

	public void lostOwnership(Clipboard clipboard, Transferable contents) {
	}
}

class RDHFlavor extends DataFlavor {
	static RDHFlavor rdhFlavor = createConstant(RDHFlavor.class, "hoge");

	public RDHFlavor(Class<?> representationClass, String humanPresentableName) {
		super(representationClass, humanPresentableName);
	}

	static private RDHFlavor createConstant(Class rc, String prn) {
		try {
			return new RDHFlavor(rc, prn);
		} catch (Exception e) {
			return null;
		}
	}
}