/*
 * This file is part of the DistSim distributed simulation framework (client)
 * Copyright (C) 2007 Ulf Hermann
 *
 * 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 2
 * 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, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package brn.distsim.client.tableModels;

import java.awt.event.ActionEvent;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import javax.swing.JTable;

import brn.distsim.client.DBConnector;
import brn.distsim.client.data.Group;
import brn.distsim.client.data.GroupNumericParameters;
import brn.distsim.client.data.GroupStringParameters;
import brn.distsim.client.data.Study;
import brn.distsim.client.data.GroupNumericParameters.Parameter;
import brn.distsim.client.ui.ClientFrame;
import brn.distsim.client.ui.ParameterDialog;


public class ParametersTableModel extends AddRemoveTableModel<Study> {

	private int stringStart;

	private List<String> stringVals;

	private String displayedText[] = new String[3];

	private static final long serialVersionUID = -7070362041897241214L;

	public ParametersTableModel(ClientFrame frame, Study newData,
			JTable parametersTable) {
		super(frame, newData, parametersTable, new ArrayList<String>());
		stringVals = new LinkedList<String>();
		// readData();
	}

	public int getColumnCount() {
		return data.size() + 1;
	}

	public String getColumnName(int columnIndex) {
		if (columnIndex == 0)
			return "Parameters";
		return data.get(columnIndex - 1).getName();
	}

	public int getRowCount() {
		return names.size();
	}

	public Object getValueAt(int rowIndex, int columnIndex) {
		String name = names.get(rowIndex);
		if (columnIndex == 0) {
			return name;
		} else if (columnIndex > data.size()) {
			return null;
		} else {
			if (rowIndex < stringStart) {
				Parameter param = data.get(columnIndex - 1)
						.getNumericParameters().get(name);
				if (param != null) {
					displayedText[0] = param.getMin();
					displayedText[1] = param.getMax();
					displayedText[2] = param.getStep();
					return displayedText;
				}

			} else {
				stringVals.clear();
				GroupStringParameters.Parameter prop = data
						.get(columnIndex - 1).getStringParameters().get(name);
				while (prop != null) {
					stringVals.add(prop.getValue());
					prop = prop.getNext();
				}
				return stringVals;
			}
		}
		return null;
	}

	public boolean isCellEditable(int rowIndex, int columnIndex) {
		if (columnIndex > 0 && data.isInserted(columnIndex - 1))
			return true;
		else
			return false;
	}

	public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
		String name = names.get(rowIndex);
		if (rowIndex < stringStart) {
			String[] content = (String[]) aValue;
			GroupNumericParameters pars = data.get(columnIndex - 1)
					.getNumericParameters();
			pars.put(pars.new Parameter(name, content[0], content[1],
					content[2]));
		} else {
			GroupStringParameters pars = data.get(columnIndex - 1)
					.getStringParameters();
			Set values = (Set) aValue;
			GroupStringParameters.Parameter par = pars.get(name);
			while (par != null) {
				String val = par.getValue();
				if (!values.remove(val)) {
					pars.remove(par);
				}
				par = par.getNext();
			}
			for (Object val : values) {
				pars.add(name, (String)val);
			}
		}
		fireTableCellUpdated(rowIndex, columnIndex);
	}

	@Override
	public int getSelected() {
		return subject.getSelectedRow();
	}

	@Override
	public void setSelected(int pos) {
		subject.setRowSelectionInterval(pos, pos);
	}

	@Override
	protected String create() {
		return null;
	}

	@Override
	protected boolean remove(int pos) {
		String name = names.get(pos);
		boolean string = false;
		boolean success = true;
		if (pos >= stringStart) {
			string = true;
		} else {
			stringStart--;
		}
		for (int i = 0; i < data.size(); ++i) {
			Group g = data.get(i);
			if (!data.isInserted(i)) {
				if ((string && g.getStringParameters().get(name) != null)
						|| (!string && g.getNumericParameters().get(name) != null))
					success = false;
			} else {
				if (string) {
					g.getStringParameters().remove(name);
				} else {
					g.getNumericParameters().remove(name);
				}
			}
		}
		if (success)
			names.remove(pos);
		return success;
	}

	public int getStringStart() {
		return stringStart;
	}

	protected boolean examineAction(ActionEvent e) throws SQLException {
		if (e.getActionCommand().equals("create")) {
			ParameterDialog d = new ParameterDialog();
			String name = d.getName();
			if (name == null)
				return true;
			if (d.getType() == ParameterDialog.NUMERIC) {
				names.add(stringStart, name);
				stringStart++;
			} else {
				names.add(name);
			}
			fireTableStructureChanged();
			return true;
		} else
			return super.examineAction(e);
	}

	@Override
	public void readData() {
		try {
			names.clear();
			names.addAll(GroupNumericParameters.getNames(DBConnector
					.getDefinitions(), data.getId()));
			stringStart = names.size();
			names.addAll(GroupStringParameters.getNames(DBConnector
					.getDefinitions(), data.getId()));
			fireTableStructureChanged();
		} catch (SQLException e) {
			error(e);
		}
	}

}
