package pbl2011.gui;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.GridLayout;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

import pbl2011.common.CommonConst;
import pbl2011.model.ClassNode;
import pbl2011.model.Method;
import pbl2011.model.Parameter;
import pbl2011.mvc.Model;

/**
 * 引数編集画面クラス
 * <p>
 *
 * @author 10745104 Y.Ishii
 *
 */
public class ParameterEditor extends JComponent implements CommonConst {

	private Model myModel;
	protected ParameterController myController;

	public ParameterEditor(Model m) {
		myModel = m;
		myController = makeController();
		initialize();
	}

	private JTextField methodText;
	private JTextField visiText;
	private JTextField returnText;
	private JButton boUp;
	private JButton boDown;

	private JTable table;
	private JTableHeader tableHeader;
	private int methodNo;
	private boolean showFlg = true;

	private ClassNode clone;

	protected void drawOne() {
		JPanel p = new JPanel();
		removeAll();
		p.setLayout(new BorderLayout());
		p.add(getTopPanel(), BorderLayout.NORTH);
		p.add(new JScrollPane(getParamTable()), BorderLayout.CENTER);

		p.add(getButton(), BorderLayout.SOUTH);

		// comboの設定
		JComboBox cb = new JComboBox(myModel.getTypeList());
		cb.setEditable(true);
		cb.setBorder(BorderFactory.createEmptyBorder());

		TableColumnModel tcm = table.getColumnModel();
		TableColumn tc = tcm.getColumn(1);
		tc.setCellEditor(new DefaultCellEditor(cb)); // 編集

		add(p);
		setBtnEnabled();
		validate();
	}
	DefaultTableModel tableModel ;
	private Component getParamTable() {

		JPanel p = new JPanel();
		String[][] data;
		if (isMethodSelect()) {

			List<Parameter> li = ((Method) clone.methodList.get(methodNo)).parameterList;
			data = new String[li.size()][3];

			int i = 0;
			for (Parameter pa : ((Method) clone.methodList.get(methodNo)).parameterList) {
				data[i][0] = pa.parameterName;
				data[i][1] = myModel.getTypeNameByTypeId(pa.dataTypeId);
				i++;
			}
		} else {
			data = new String[0][2];
		}
		String[] tableCol = { "引数名", "引数型" };

		removeAll();
		tableModel = new DefaultTableModel(data, tableCol);
		tableModel.addTableModelListener(new TableModelListener() {

			@Override
			public void tableChanged(TableModelEvent e) {

				int sc = table.getSelectedRow();
				if(sc > -1) {
					clone.changeParameter(methodNo, sc, (String) table
						.getValueAt(sc, 0), myModel.getTypeIdByTypeName((String) table.getValueAt(sc, 1)));
				}
			}
		});

		table = new JTable(tableModel);
		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		tableHeader = table.getTableHeader();

		p.setLayout(new BorderLayout());
		p.add(tableHeader, BorderLayout.NORTH);
		p.add(table, BorderLayout.CENTER);
		validate();

		return p;

	}

	protected void initialize() {

		setLayout(new BorderLayout());

		drawOne();

		setVisible(true);
	}

	private Component getTopPanel() {
		String methodName = "";
		String dataType = "";
		VisibilityType visibility = VisibilityType.UNDEF;

		if (isMethodSelect()) {
			Method m = (Method) clone.methodList.get(methodNo);
			methodName = m.methodName;
			dataType = myModel.getTypeNameByTypeId(m.dataTypeId);
			visibility = m.visibility;
		}
		JPanel p = new JPanel();
		p.setLayout(new GridLayout(3, 3));

		JLabel l1 = new JLabel("名前");
		JLabel l2 = new JLabel("返り値");
		JLabel l3 = new JLabel("可視性");
		methodText = new JTextField(methodName);
		methodText.setEditable(false);
		returnText = new JTextField(dataType);
		returnText.setEditable(false);
		visiText = new JTextField(visibility.alias());
		visiText.setEditable(false);

		boUp = new JButton("↑");
		boUp.setActionCommand(UP);
		boUp.addActionListener(myController);
		boDown = new JButton("↓");
		boDown.setActionCommand(DOWN);
		boDown.addActionListener(myController);

		p.add(l1);
		p.add(methodText);
		p.add(boUp);
		p.add(l2);
		p.add(returnText);
		p.add(boDown);
		p.add(l3);
		p.add(visiText);
		return p;
	}

	private boolean isMethodSelect() {
		return clone != null && showFlg	&&
			clone.methodList.size() > methodNo && methodNo > -1;
	}

	JButton bo1;
	JButton bo2;

	private Component getButton() {
		JPanel p = new JPanel();
		p.setLayout(new GridLayout(1, 4));
		bo1 = new JButton("追加");
		bo1.setActionCommand(ADD);
		bo1.addActionListener(myController);
		bo2 = new JButton("削除");
		bo2.setActionCommand(DELETE);
		bo2.addActionListener(myController);

		p.add(bo1);
		p.add(bo2);
		return p;
	}

	protected ParameterController makeController() {
		// 詳細画面のコントローラを使用
		return new ParameterController(this);
	}

	void setSelectLine(int selectLine) {
		this.methodNo = selectLine;
		drawOne();

	}

	public void setBtnEnabled() {
		bo1.setEnabled(showFlg);
		bo2.setEnabled(showFlg);
		boUp.setEnabled(showFlg);
		boDown.setEnabled(showFlg);
	}

	public void addModel() {
		clone.addParameter(methodNo);
		tableModel.addRow(new String[]{"new parameter", "String"});
	}

	public void deleteModel() {
		if ( table.getSelectedRow() > -1 ) {
			clone.deleteParameter(methodNo, table.getSelectedRow());
			tableModel.removeRow(table.getSelectedRow());
		}
	}

	public void up() {
		int row = table.getSelectedRow();
		if ( row > 0 ) {
			clone.changeParameterSeq(methodNo, table.getSelectedRow(), true);
			tableModel.moveRow(row,row, row-1 );
			table.setRowSelectionInterval(row-1,row-1);
		}
	}

	public void down() {
		int row = table.getSelectedRow();
		if ( row > -1 && row < table.getRowCount()-1) {
			clone.changeParameterSeq(methodNo, table.getSelectedRow(), false);
			tableModel.moveRow(row,row, row+1 );
			table.setRowSelectionInterval(row+1,row+1);
		}
	}

	public void setShowFlg(boolean flg) {
		this.showFlg =flg;

	}

	protected void setClassNode(ClassNode cn) {
		clone = cn;
	}
}
