/**
 * <p>
 * Copyright © 2009-2010, Bruce-Robert Pocock
 * </p>
 * <p>
 * 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 3 of the License, or (at
 * your option) any later version.
 * </p>
 * <p>
 * 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.
 * </p>
 * <p>
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 * </p>
 * 
 * @author brpocock
 */

package org.starhope.appius.mb;

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

import org.json.JSONException;
import org.json.JSONObject;
import org.starhope.appius.except.DataException;
import org.starhope.appius.except.NotFoundException;
import org.starhope.appius.game.AppiusClaudiusCaecus;
import org.starhope.appius.sql.SQLPeerEnum;
import org.starhope.appius.util.AppiusConfig;

/**
 * @author brpocock
 * 
 */
public class Currency extends SQLPeerEnum {

	/**
	 * 
	 */
	private static final long serialVersionUID = -6340388141547546058L;

	/**
	 * @param object the JSON data describing the currency wanted
	 * @return the Currency object
	 * @throws JSONException if the JSON data is badly-formed
	 * @throws NotFoundException if the object isn't found in the
	 *         database
	 * @throws RuntimeException if something else bad happens
	 */
	public static Currency get (final JSONObject object)
	throws RuntimeException, NotFoundException, JSONException {
		return new Currency (0);
	}

	/**
	 * @param id database ID
	 * @return currency with that database ID
	 * @throws NotFoundException if it's not found in the database
	 * @throws RuntimeException if something else wonky were to happen
	 */
	public static Currency get (final String id)
	throws RuntimeException, NotFoundException {
		Connection con = null;
		PreparedStatement st = null;
		Currency cur = null;
		try {
			con = AppiusConfig.getDatabaseConnection ();
			st = con
			.prepareStatement ("SELECT * FROM currency WHERE code=?");

			st.setString (1, id);
			st.execute ();
			cur = new Currency (st.getResultSet ());
		} catch (final SQLException e) {
			AppiusClaudiusCaecus.reportBug (e);
		} finally {
			if (null != st) {
				try {
					st.close ();
				} catch (final SQLException e) { /* No Op */
				}
			}
			if (null != con) {
				try { con.close (); } catch (final SQLException e) { /* No Op */ }
			}
		}
		return cur;
	}

	/**
	 * This is a quick "semantic sugar" to pick up U.S. Dollars as a
	 * currency format, since that's realistically the only one we're
	 * dealing with at the moment.
	 * 
	 * @return a Currency object representing U.S. Dollars.
	 */
	public static Currency get_USD () {
		final Currency dollar = new Currency ();
		dollar.code = "USD";
		dollar.symbol = "$";
		return dollar;
	}

	/**
	 * @param string ISO-4217 currency code
	 * @return a Currency object
	 * @throws NotFoundException if it can't be found
	 */
	public static Currency getByCode (final String string)
	throws NotFoundException {
		return Currency.get ("code=" + string);
	}

	/**
	 * The ISO-4217 currency code (three letters); "USD" is U.S. Dollar,
	 * and "EUR" is the Euro.
	 */
	private String code;

	/**
	 * The display character sequence. For US Dollars, it's " US $ ";
	 * for Euros, it's just the Euro sign
	 */
	private String symbol;

	/**
	 * WRITEME
	 */
	private Currency () {
		super (Currency.class);
	}

	/**
	 * @param id The integral ID number for the type of currency to be
	 *        instantiated
	 */
	protected Currency (final int id) {
		super (Currency.class, id);
		// TODO Auto-generated constructor stub
	}

	/**
	 * @param resultSet the SQL row from which to instantiate this
	 *        currency object
	 */
	private Currency (final ResultSet resultSet) {
		super (Currency.class);
		this.set (resultSet);
	}

	/**
	 * @see org.starhope.appius.sql.SQLPeerEnum#cache(java.sql.ResultSet)
	 */
	@Override
	protected void cache (final ResultSet set) throws SQLException {
		// TODO Auto-generated method stub
	}

	/**
	 * @see org.starhope.appius.sql.SQLPeerDatum#flush()
	 */
	@Override
	public void flush () {
		// TODO Auto-generated method stub

	}

	/**
	 * This is an overriding method.
	 *
	 * @see org.starhope.appius.sql.SQLPeerDatum#getCacheUniqueID()
	 */
	@Override
	protected String getCacheUniqueID () {
		return "Currency/" + getCode ();
	}

	/**
	 * Get the three-character (ISO-4217) currency code.
	 * 
	 * @return A string of three uppercase characters
	 */
	public String getCode () {
		return code;
	}

	/**
	 * @see org.starhope.appius.sql.SQLPeerEnum#getStatement(java.sql.Connection)
	 */
	@Override
	protected PreparedStatement getStatement (
			final Connection connection) {
		/* TEMPORARY FIX UNTIL THIS CLASS IS FULLY WRITTEN */
		try {
			return connection
			.prepareStatement ("SELECT * FROM currencies");
		} catch (final SQLException e) {
			throw AppiusClaudiusCaecus.fatalBug (e);
		}
	}

	/**
	 * @see #setSymbol Returns the currency symbol for user presentation
	 *      of prices.
	 * @return A string of 1-5 characters suitable for unambiguous
	 *         representation of this currency.
	 */
	public String getSymbol () {
		return symbol;
	}

	/**
	 * @see org.starhope.appius.util.CastsToJSON#set(org.json.JSONObject)
	 */
	@Override
	public void set (final JSONObject o) {
		try {
			setCode (o.optString ("code"));
			setSymbol (o.optString ("symbol"));
		} catch (final DataException e) {
			AppiusClaudiusCaecus.reportBug (e);
			throw new Error (e);
		}
	}

	/**
	 * @see org.starhope.appius.sql.SQLPeerDatum#set(java.sql.ResultSet)
	 */
	@Override
	protected void set (final ResultSet rs) {
		// TODO Auto-generated method stub

	}

	/**
	 * Change the currency code for this instance.
	 * 
	 * @param newCode The new currency code to be set (ISO-4217,
	 *        uppercase, e.g. "USD")
	 * @throws DataException if the specification does not consist of
	 *         three AppiusCharacter.UPPERCASE_LETTER characters.
	 */
	public void setCode (final String newCode) throws DataException {
		if (newCode.length () != 3
				|| Character.getType (newCode.charAt (0)) != Character.UPPERCASE_LETTER
				|| Character.getType (newCode.charAt (1)) != Character.UPPERCASE_LETTER
				|| Character.getType (newCode.charAt (3)) != Character.UPPERCASE_LETTER)
			throw new DataException (
			"Code must be a three-character ISO-4217 code in uppercase, e.g. USD");
		code = newCode;
		changed ();
	}

	/**
	 * Set the user-visible displayed symbol of this currency. E.G. for
	 * the US Dollar, this is "US $"; Mexican New Peso, "Mx $"; for the
	 * Canadian dollar, "CA $"; for the Chinese RMB, it might be "RMB",
	 * versus Japanese Yen "Jp ¥"; Euro, just "€" (since there's no
	 * confusion with any other country using a similar currency symbol)
	 * 
	 * @param newSymbol The new symbol string to be used for this
	 *        currency
	 * @throws DataException if the new symbol string is not supplied,
	 *         or is more than 5 characters long
	 */
	public void setSymbol (final String newSymbol) throws DataException {
		if (null == newSymbol || newSymbol.length () == 0)
			throw new DataException ("Currency symbol must be given");
		if (newSymbol.length () > 5)
			throw new DataException (
			"Currency symbol length must be less than 5 characters");
		symbol = newSymbol;
		changed ();
	}

}
