package de.yogularm.minecraft.itemfinder.gui;

import java.awt.*;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableRowSorter;

import org.jdesktop.swingx.JXTable;

import de.yogularm.minecraft.itemfinder.region.DroppedItem;

public class ItemList {
	private Component component;
	private JXTable table;
	private ItemTableModel model;
	private TableRowSorter<ItemTableModel> sorter;
	private JPopupMenu contextMenu;

	public ItemList() {
		initUI();
	}

	private void initUI() {
		model = new ItemTableModel();
		table = new JXTable(model);
		sorter = new TableRowSorter<>(model);
		table.setRowSorter(sorter);
		sorter.setComparator(0, new NaturalOrderComparator()); // for item name
		sorter.setSortKeys(Arrays.asList(
				new RowSorter.SortKey(4, SortOrder.DESCENDING),
				new RowSorter.SortKey(3, SortOrder.ASCENDING)));
		
		table.getColumnModel().getColumn(0).setWidth(200);

		component = new JScrollPane(table);

		contextMenu = new JPopupMenu();
		JMenuItem copyItem = new JMenuItem("Copy");
		copyItem.addActionListener(new ActionListener() {
			@Override public void actionPerformed(ActionEvent actionEvent) {
				Object text = model.getValueAt(sorter.convertRowIndexToModel(table.getSelectedRow()),
						table.getSelectedColumn());
				if (text == null) {
					return;
				}
				Toolkit.getDefaultToolkit().getSystemClipboard()
						.setContents(new StringSelection(text.toString()), null);
			}
		});
	 	contextMenu.add(copyItem);

		// manually show the popup menu so that the cell under the mouse is selected first
		table.addMouseListener(new MouseAdapter() {
			public void mousePressed(MouseEvent e) {
				// Left mouse click
				if (SwingUtilities.isLeftMouseButton(e)) {
					// Do something
				}
				// Right mouse click
				else if (SwingUtilities.isRightMouseButton(e)) {
					// get the coordinates of the mouse click
					Point p = e.getPoint();

					// get the row index that contains that coordinate
					int rowNumber = table.rowAtPoint(p);

					// Get the ListSelectionModel of the JTable
					ListSelectionModel model = table.getSelectionModel();

					// set the selected interval of rows. Using the "rowNumber"
					// variable for the beginning and end selects only that one row.
					model.setSelectionInterval(rowNumber, rowNumber);

					int colNumber = table.columnAtPoint(p);
					table.getColumnModel().getSelectionModel().setSelectionInterval(colNumber, colNumber);

					contextMenu.show(table, p.x, p.y);
				}
			}
		});

	}

	public void setItems(List<DroppedItem> items) {
		model.setItems(items);
		table.packAll(); // adjust column widths
	}

	public Component getComponent() {
		return component;
	}

	private static class ItemTableModel extends AbstractTableModel {
		private static final long serialVersionUID = 1904800093497922295L;

		private static final String[] COLUMNS = new String[] { "Item Name",
				"Stack Size", "Location", "Age", "Chunk Update" };

		private List<DroppedItem> items;

		public ItemTableModel() {
			this.items = new ArrayList<>();
		}

		public void setItems(List<DroppedItem> items) {
			this.items = items;
			fireTableDataChanged();
		}

		@Override
		public int getColumnCount() {
			return COLUMNS.length;
		}

		@Override
		public String getColumnName(int column) {
			return COLUMNS[column];
		}

		@Override
		public int getRowCount() {
			return items.size();
		}

		@Override
		public Object getValueAt(int rowIndex, int columnIndex) {
			if (rowIndex >= items.size())
				return "";
			DroppedItem item = items.get(rowIndex);
			switch (columnIndex) {
			case 0:
				return item.getName();
			case 1:
				return item.getCount();
			case 2:
				return item.getPosition().toRoundedString();
			case 3:
				// there are items with age 0 which should be displayed at the bottom
				// HourSecond will render Integer.MAX_VALUE as --
				return new HourSecond(item.getAge() == 0 ? Integer.MAX_VALUE : item.getAge() / 20);
			case 4:
				return new RelativeTime(- item.getRelativeChunkUpdateTime());
			default:
				return "";
			}
		}

		@Override
		public Class<?> getColumnClass(int columnIndex) {
			switch (columnIndex) {
			case 0:
				return String.class;
			case 1:
				return Integer.class;
			case 2:
				return String.class;
			case 3:
				return HourSecond.class;
			case 4:
				return RelativeTime.class;
			default:
				return null;
			}
		}
	}
}

@@ -1446,21 +1446,21 @@
  text = 
-model
+table
 .getValu
@@ -1467,38 +1467,8 @@
 eAt(
-sorter.convertRowIndexToModel(
 tabl
@@ -1489,17 +1489,10 @@
 ow()
-),%0A%09%09%09%09%09%09
+, 
 tabl

Fix copy column content when columns are reordered