/*
 * 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.data;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.Properties;

public class Simulation extends DbBackedProperties<Simulation.Parameter>
		implements Saveable {

	public static final String TABLE_NAME = "params";

	public class Parameter extends DbBackedProperties.Property {

		public Parameter(String name, String value) {
			super(name, value);
		}

		public Parameter(Parameter p) {
			super(p.name, p.value);
		}

		public void performDbInsert(int simulationId) throws SQLException {
			statement.executeUpdate("INSERT INTO " + TABLE_NAME + " VALUES ("
					+ simulationId + ", '" + name + "', '" + value + "');");
		}

		public void performDbDelete() throws SQLException {
			statement
					.executeUpdate("DELETE FROM " + TABLE_NAME
							+ " WHERE simulationId=" + id + " AND name='"
							+ name + "';");
		}

		public void performDbUpdate() throws SQLException {
			statement.executeUpdate("REPLACE INTO " + TABLE_NAME + " VALUES ("
					+ id + ", '" + name + "', '" + value + "');");
		}

	}

	protected int groupId;

	protected int hostId;
	
	private Timestamp defined;
	
	private Progress progress;

	public Simulation(Connection db, ResultSet simulations) throws SQLException {
		super(db, simulations.getInt("id"));
		groupId = simulations.getInt("groupId");
		hostId = simulations.getInt("assigned");
		defined = simulations.getTimestamp("defined");
		loadFromDb(statement.executeQuery("SELECT * FROM " + TABLE_NAME
				+ " WHERE simulationId=" + id + ";"));
	}

	public void loadProgress(Connection results) throws SQLException {
		progress = new Progress(results, id);
		progress.loadFromDb();
	}
	
	public Progress getProgress() {
		return progress;
	}
	
	public Simulation(Connection definitions, int groupId) {
		super(definitions, 0);
		this.groupId = groupId;
	}

	public Simulation(Simulation other) {
		super(other.definitions, 0);
		groupId = other.groupId;
	}

	public Simulation(Simulation other, int groupId) {
		super(other.definitions, 0);
		this.groupId = groupId;
	}

	public void performDbDelete() throws SQLException {
		deleteAll();
		commit();
		statement.executeUpdate("DELETE FROM simulations WHERE id=" + id
				+ " AND assigned<=>NULL;");
	}

	public void performDbInsert(int groupId) throws SQLException {
		this.groupId = groupId;
		statement
				.executeUpdate("INSERT INTO simulations SET groupId=" + groupId
						+ ", defined=NOW();", Statement.RETURN_GENERATED_KEYS);
		ResultSet key = statement.getGeneratedKeys();
		key.next();
		id = key.getInt(1);
		commit();
	}

	public void performDbUpdate() throws SQLException {
		statement.executeUpdate("REPLACE INTO simulations SET groupId="
				+ groupId + ", defined=NOW() WHERE id=" + id + ";");
		commit();
	}

	@Override
	public Parameter getEmptyDependent() {
		return new Parameter(null, null);
	}

	@Override
	public Parameter getDependent(ResultSet data) throws SQLException {
		return new Parameter(data.getString("name"), data.getString("value"));
	}

	@Override
	public Parameter getDependent(Parameter other) {
		return new Parameter(other.name, other.value);
	}

	@Override
	public void loadFromDb() throws SQLException {
		ResultSet sim = statement
				.executeQuery("SELECT * FROM simulations WHERE id=" + id + ";");
		if (sim.next()) {
			groupId = sim.getInt("groupId");
			hostId = sim.getInt("assigned");
			defined = sim.getTimestamp("defined");
			ResultSet params = statement.executeQuery("SELECT * FROM "
					+ TABLE_NAME + " WHERE simulationId=" + id + ";");
			super.loadFromDb(params);
		}
	}

	public String getName() {
		return "simulation:" + groupId + ":" + id;
	}

	public void put(Properties props) {
		for (Object name : props.keySet()) {
			put(new Parameter(name.toString(), props.get(name).toString()));
		}
	}

	public int getGroupId() {
		return groupId;
	}

	public int getHost() {
		return hostId;
	}
	
	public Timestamp getDefined() {
		return defined;
	}

	public Results getResults(Connection results) throws SQLException {
		return new Results(results, id);
	}

	public void unassign() throws SQLException {
		statement.executeUpdate("UPDATE simulations SET assigned=NULL WHERE id=" + id + ";");
	}
}
