/**
 * 
 */
package cz.neubauer.tomas.hazardanalysis.model.dangers;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * Třída, která reprezentuje variantu typu nebezpečí.
 * 
 * @author Tomáš Neubauer
 */
public class DangerVariant implements Comparable<DangerVariant> {
	/**
	 * ID - hodnota primárního klíče posledního vkládaného zaáznamu v databázi.
	 * Sdílená promenná používaná pro generování klíče pro vkládání nového
	 * záznamu do tabulky v databázi.
	 */
	private static int last_insert_id = -1;

	/**
	 * Klíč záznamu v datavázi.
	 */
	private int id;

	/**
	 * Popis varianty.
	 */
	private String description;

	/**
	 * Informace o tom, je-li varianta závažná (kritická).
	 */
	private boolean critical;

	/**
	 * Informace o tom, je-li varianta vybrána (ve formuláři).
	 */
	private boolean selected;

	/**
	 * Typ nebezpeci, do ktereho patri tato varianta.
	 */
	private DangerType dangerType;

	/**
	 * Vytvoří variantu typu nebezpečí s danými atributy.
	 * 
	 * @param owner
	 *            Vlastník - Typ nebezpečí, do kterého varianta patří.
	 * @param id
	 *            Klíč záznamu v databázi.
	 * @param description
	 *            Popis varianty.
	 */
	public DangerVariant(DangerType owner, int id, String description) {
		this.id = id;
		dangerType = owner;
		this.description = description;
		critical = false;
		selected = false;
	}

	/**
	 * Vrátí popis varianty.
	 * 
	 * @return Popis varianty.
	 */
	public String getDescription() {
		return description;
	}

	/**
	 * Nastaví popis varianty.
	 * 
	 * @param description
	 *            Nový popis varianty.
	 */
	public void setDescription(String description) {
		this.description = description;
	}

	/**
	 * Vrátí typ, do kterého varianta patří.
	 * 
	 * @return Typ, do kterého vatianta patří.
	 */
	public DangerType getDangerType() {
		return dangerType;
	}

	/**
	 * Nastaví typ, do kterého varianta patří.
	 * 
	 * @param dangerType
	 *            Nový typ, do kterého varianta patří.
	 */
	public void setDangerType(DangerType dangerType) {
		this.dangerType = dangerType;
	}

	/**
	 * Vrátí informaci o tom, zda-li je varianta závažná (kritická).
	 * 
	 * @return Informace o tom, zda-li je varianta závažná (kritická).
	 */
	public boolean isCritical() {
		return critical;
	}

	/**
	 * Nastaví informaci o tom, zda-li je varianta závažná (kritická).
	 * 
	 * @param critical
	 *            Nová informace o tom, zda-li je varianta závažná (kritická).
	 */
	public void setCritical(boolean critical) {
		this.critical = critical;
	}

	/**
	 * Vrátí klíč záznamu v databázové tabulce.
	 * 
	 * @return Klíč záznamu.
	 */
	public int getId() {
		return id;
	}

	/**
	 * Nastaví klíč záznamu.
	 * 
	 * @param id
	 *            Nový klíč záznamu.
	 */
	public void setId(int id) {
		this.id = id;
	}

	/**
	 * Uloží záznam do databáze prostřednictvím daného připojení. Pokud se v
	 * tabulce záznam s daným klíčem nachází, pouze jej aktualizuje (UPDATE),
	 * jinak se do tabulky vloží nový záznam (INSERT).
	 * 
	 * @param con
	 *            Připojení k databázi.
	 */
	public void saveToDB(Connection con) {
		if (con != null) {
			try {
				Statement stmt = con.createStatement();
				if (last_insert_id < 1) {
					stmt.executeQuery("SELECT max(id) FROM danger_variant;");
					ResultSet rs = stmt.getResultSet();
					if (rs.next()) {
						last_insert_id = rs.getInt(1);
					}
				}
				stmt
						.executeQuery("SELECT count(id) as count FROM danger_variant WHERE id = '"
								+ id + "';");
				ResultSet rs1 = stmt.getResultSet();
				if (rs1.next() && rs1.getInt(1) == 0) {
					stmt.executeUpdate(
							"INSERT INTO danger_variant VALUES ("
									+ (last_insert_id > 0 ? "'"
											+ (++last_insert_id) + "'"
											: "LAST_INSERT_ID()") + ", '"
									+ dangerType.getId() + "', '" + description
									+ "');", Statement.RETURN_GENERATED_KEYS);
					ResultSet rs = stmt.getGeneratedKeys();
					if (rs.next()) {
						id = rs.getInt(1);
						last_insert_id = id;
					}
				} else {
					stmt
							.executeUpdate("UPDATE danger_variant SET danger_type_id='"
									+ dangerType.getId()
									+ "', description = '"
									+ description + "' WHERE id='" + id + "';");
				}
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * Smaže záznam z databáze prostřednictvím daného připojení a zruší
	 * instanci.
	 * 
	 * @param con
	 *            Připojení k databázi.
	 */
	public void deleteFromDB(Connection con) {
		if (con != null) {
			Statement stmt;
			try {
				stmt = con.createStatement();
				// smazání přiřazení varianty komponentám

				stmt
						.executeUpdate("DELETE FROM component_danger_variant WHERE danger_variant_id = '"
								+ id + "';");

				stmt.executeUpdate("DELETE FROM danger_variant WHERE id = '"
						+ id + "';");
				stmt.close();
				finalize();
			} catch (SQLException e) {
				e.printStackTrace();
			} catch (Throwable e) {
				e.printStackTrace();
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return description;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (obj instanceof DangerVariant) {
			return ((DangerVariant) obj).getId() == id;
		}
		return false;
	}

	/**
	 * Vrátí informaci o tom, zda-li je varianta označena jako závažná
	 * (kritická), nebo ne.
	 * 
	 * @return <code>true</code>, pokud je varianta označena jako závažná,
	 *         jinak vrátí <code>false</code>.
	 */
	public boolean isSelected() {
		return selected;
	}

	/**
	 * Nastaví variantě informaci o tom, zda-li je závažná (kritická), nebo
	 * není.
	 * 
	 * @param selected
	 *            Informace o tom, je-li varianta závažná, či není.
	 */
	public void setSelected(boolean selected) {
		this.selected = selected;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Comparable#compareTo(java.lang.Object)
	 */
	@Override
	public int compareTo(DangerVariant o) {
		if (id < o.id) {
			return -1;
		} else if (equals(o)) {
			return 0;
		} else {
			return 1;
		}
	}
}
