/**
 * Copyright © 2009-2010, Res Interactive, LLC. All Rights Reserved.
 */

package com.tootsville;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.*;
import java.util.Random;

import javax.mail.MessagingException;

import org.starhope.appius.except.NotFoundException;
import org.starhope.appius.game.AppiusClaudiusCaecus;
import org.starhope.appius.messaging.Mail;
import org.starhope.appius.sql.SQLPeerDatum;
import org.starhope.appius.user.Person;
import org.starhope.appius.util.AppiusConfig;

/**
 * 
 * TODO: The documentation for this type (Coupon) is incomplete. (theys,
 * Nov 3, 2009)
 * 
 * @author theys
 * 
 */
public class Coupon extends SQLPeerDatum {
	/**
	 * TODO: document this field (theys, Nov 3, 2009)
	 * 
	 * orderCodeChars (Coupon)
	 */
	private static final char orderCodeChars[] = { 'A', 'B', 'C', 'D',
		'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S',
		'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4',
		'5', '6', '7', '8', '9' };

	/**
	 * TODO: document this field (theys, Oct 28, 2009)
	 * 
	 * serialVersionUID (long)
	 */
	private static final long serialVersionUID = -910537582879371680L;

	/**
	 * 
	 * TODO: document this method (theys, Sep 29, 2009)
	 * 
	 * @return WRITEME
	 */
	private static String generateRandomCode () {
		String eCode = "";
		boolean found = false;
		final Random rnd = new Random ();

		PreparedStatement checkExists = null;
		try {
			checkExists = AppiusConfig
			.getStoreDatabaseConnection ()
			.prepareStatement (
			"SELECT COUNT(*) FROM zen_coupons WHERE coupon_code=?");
			do {
				// generate 10 random characters from the given
				for (int i = 0; i < 12; ++i) {
					eCode += String
					.valueOf (Coupon.orderCodeChars [(int) (rnd
							.nextDouble () * Coupon.orderCodeChars.length)]);
				}
				checkExists.setString (1, eCode);
				if (checkExists.execute ()) {
					final ResultSet exists = checkExists
					.getResultSet ();
					exists.next ();
					if (exists.getInt (1) == 0) {
						found = true;
					}
				}
			} while (!found);
			checkExists.close ();
		} catch (final SQLException e) {
			throw AppiusClaudiusCaecus.fatalBug (e);
		} finally {
			if (null != checkExists) {
				try {
					checkExists.close ();
				} catch (final SQLException e) {
					AppiusClaudiusCaecus.reportBug ("finally", e);
				}
			}
		}

		return eCode;
	}

	/**
	 * TODO: document this field (theys, Nov 3, 2009)
	 * 
	 * couponAmount (Coupon)
	 */
	private BigDecimal couponAmount = new BigDecimal (14.95);
	/**
	 * TODO: document this field (theys, Nov 3, 2009)
	 * 
	 * couponCode (Coupon)
	 */
	private String couponCode;
	/**
	 * TODO: document this field (theys, Nov 3, 2009)
	 * 
	 * couponDescription (Coupon)
	 */
	private String couponDescription = "Free Plush Toot order code for V.I.T. membership.  Thank you!  Redeem for Toots Account: ";
	/**
	 * TODO: document this field (theys, Nov 3, 2009)
	 * 
	 * couponID (Coupon)
	 */
	private int couponID;

	/**
	 * TODO: document this field (theys, Nov 3, 2009)
	 * 
	 * couponMinAmount (Coupon)
	 */
	private BigDecimal couponMinAmount = new BigDecimal (0);

	/**
	 * TODO: document this field (theys, Nov 3, 2009)
	 * 
	 * couponName (Coupon)
	 */
	private String couponName = "Free Plush Toot";

	/**
	 * TODO: document this field (theys, Nov 3, 2009)
	 * 
	 * endDate (Coupon)
	 */
	private Date endDate = Date.valueOf ("2010-1-1");

	/**
	 * TODO: document this field (theys, Nov 3, 2009)
	 * 
	 * startDate (Coupon)
	 */
	private Date startDate = new Date (System.currentTimeMillis ());

	/**
	 * TODO: document this field (theys, Nov 3, 2009)
	 * 
	 * usesPerCoupon (Coupon)
	 */
	private int usesPerCoupon = 1;

	/**
	 * TODO: document this field (theys, Nov 3, 2009)
	 * 
	 * usesPerUser (Coupon)
	 */
	private int usesPerUser = 1;

	/**
	 * @param userName TODO
	 */
	public Coupon (final String userName) {
		// default setter (theys, Oct 28, 2009)
		couponDescription = "Free Plush Toot order code for V.I.T. membership.  Thank you!  Redeem for Toots Account: "
			+ userName;
		couponCode = Coupon.generateRandomCode ();

		insertCoupon ();
		insertCouponDescription ();
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.sql.SQLPeerDatum#flush()
	 */
	@Override
	public void flush () {
		// do nothing
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.sql.SQLPeerDatum#getCacheUniqueID()
	 */
	@Override
	protected String getCacheUniqueID () {
		// TODO Auto-generated method stub (theys, Oct 28, 2009)
		return null;
	}

	/**
	 * TODO: document this method (theys, Nov 3, 2009)
	 * 
	 * @return TODO
	 */
	public BigDecimal getCouponAmount () {
		// default getter (theys, Oct 28, 2009)
		return couponAmount;
	}

	/**
	 * TODO: document this method (theys, Nov 3, 2009)
	 * 
	 * @return TODO
	 */
	public String getCouponCode () {
		// default getter (theys, Oct 28, 2009)
		return couponCode;
	}

	/**
	 * TODO: document this method (theys, Nov 3, 2009)
	 * 
	 * @return TODO
	 */
	public String getCouponDescription () {
		// default getter (theys, Oct 28, 2009)
		return couponDescription;
	}

	/**
	 * TODO: document this method (theys, Nov 3, 2009)
	 * 
	 * @return TODO
	 */
	public int getCouponID () {
		// default getter (theys, Oct 28, 2009)
		return couponID;
	}

	/**
	 * TODO: document this method (theys, Nov 3, 2009)
	 * 
	 * @return TODO
	 */
	public BigDecimal getCouponMinAmount () {
		// default getter (theys, Oct 28, 2009)
		return couponMinAmount;
	}

	/**
	 * TODO: document this method (theys, Nov 3, 2009)
	 * 
	 * @return TODO
	 */
	public String getCouponName () {
		// default getter (theys, Oct 28, 2009)
		return couponName;
	}

	/**
	 * TODO: document this method (theys, Nov 3, 2009)
	 * 
	 * @return TODO
	 */
	public Date getEndDate () {
		// default getter (theys, Oct 28, 2009)
		return endDate;
	}

	/**
	 * TODO: document this method (theys, Nov 3, 2009)
	 * 
	 * @return TODO
	 */
	public Date getStartDate () {
		// default getter (theys, Oct 28, 2009)
		return startDate;
	}

	/**
	 * TODO: document this method (theys, Nov 3, 2009)
	 * 
	 * @return TODO
	 */
	public int getUsesPerCoupon () {
		// default getter (theys, Oct 28, 2009)
		return usesPerCoupon;
	}

	/**
	 * TODO: document this method (theys, Nov 3, 2009)
	 * 
	 * @return TODO
	 */
	public int getUsesPerUser () {
		// default getter (theys, Oct 28, 2009)
		return usesPerUser;
	}

	/**
	 * TODO: document this method (theys, Nov 3, 2009)
	 * 
	 */
	private void insertCoupon () {

		PreparedStatement insert = null;
		Connection storeCon = null;
		try {
			storeCon = AppiusConfig.getStoreDatabaseConnection ();
			insert = storeCon
			.prepareStatement (
					"INSERT INTO zen_coupons "
					+ "(coupon_code, coupon_amount, coupon_minimum_order, "
					+ "coupon_start_date, coupon_expire_date, uses_per_coupon, "
					+ "uses_per_user, date_created) "
					+ "VALUES (?,?,?,?,?,?,?,NOW())");

			insert.setString (1, couponCode);
			insert.setBigDecimal (2, couponAmount);
			insert.setBigDecimal (3, couponMinAmount);
			insert.setDate (4, startDate);
			insert.setDate (5, endDate);
			insert.setInt (6, usesPerCoupon);
			insert.setInt (7, usesPerUser);

			if (insert.executeUpdate () != 1)
				throw new SQLException ("adding new user failed with "
						+ insert.getUpdateCount () + " updates");
			final ResultSet keys = insert.getGeneratedKeys ();
			if (keys.next ()) {
				couponID = keys.getInt (1);
				System.out.println ("New Coupon ID: " + couponID);
			} else
				throw new SQLException ("Can't get coupon ID");
		} catch (final SQLException e) {
			AppiusClaudiusCaecus.fatalBug (e);
		} finally {
			if (null != insert) {
				try {
					insert.close ();
				} catch (final SQLException e) { /* No Op */
				}
			}
			if (null != storeCon) {
				try { storeCon.close (); } catch (final SQLException e) { /* No Op */ }
			}
		}
	}

	/**
	 * TODO: document this method (theys, Nov 3, 2009)
	 * 
	 */
	private void insertCouponDescription () {
		PreparedStatement insert = null;
		Connection storeCon = null;
		try {
			storeCon = AppiusConfig.getStoreDatabaseConnection ();
			insert = storeCon
			.prepareStatement (
					"INSERT INTO zen_coupons_description "
					+ "(coupon_id, language_id, coupon_name, coupon_description ) "
					+ "VALUES (?,?,?,?)");

			insert.setInt (1, couponID);
			insert.setInt (2, 1);
			insert.setString (3, couponName);
			insert.setString (4, couponDescription);
			insert.execute ();
		} catch (final SQLException e) {
			AppiusClaudiusCaecus.fatalBug (e);
		} finally {
			if (null != insert) {
				try {
					insert.close ();
				} catch (final SQLException e) { /* No Op */
				}
			}
			if (null != storeCon) {
				try { storeCon.close (); } catch (final SQLException e) { /* No Op */ }
			}
		}
	}

	/**
	 * TODO: document this method (theys, Nov 3, 2009)
	 * 
	 * @param user TODO
	 */
	public void sendCouponCode (final Person user) {
		try {
			user.setCouponCode (getCouponCode ());
			Mail
			.sendTemplateMail (
					user,
					AppiusConfig
					.getConfigOrNull ("com.tootsville.coupon.templates.freeplush"),
					false,
					AppiusConfig
					.getConfigOrNull ("com.tootsville.coupon.templates.freeplush.subject"));
		} catch (final FileNotFoundException e) {
			// Default catch action, report bug (theys, Oct 28, 2009)
			AppiusClaudiusCaecus.reportBug (
					"Template not found for coupon", e);
		} catch (final IOException e) {
			// Default catch action, report bug (theys, Oct 28, 2009)
			AppiusClaudiusCaecus.reportBug (
					"File unable to be loaded for coupon template", e);
		} catch (final NotFoundException e) {
			// Default catch action, report bug (theys, Oct 28, 2009)
			AppiusClaudiusCaecus.reportBug (
					"Template not found for coupon", e);
		} catch (final MessagingException e) {
			// Default catch action, report bug (theys, Oct 28, 2009)
			AppiusClaudiusCaecus.reportBug (
					"Unable to send mail for coupon", e);
		}

	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.sql.SQLPeerDatum#set(java.sql.ResultSet)
	 */
	@Override
	protected void set (final ResultSet rs) throws SQLException {
		// TODO Auto-generated method stub (theys, Oct 28, 2009)
		throw AppiusClaudiusCaecus.fatalBug ("Unimplemented method");
	}

	/**
	 * TODO: document this method (theys, Nov 3, 2009)
	 * 
	 * @param newCouponAmount TODO
	 */
	public void setCouponAmount (final BigDecimal newCouponAmount) {
		// default setter (theys, Oct 28, 2009)
		couponAmount = newCouponAmount;
	}

	/**
	 * TODO: document this method (theys, Nov 3, 2009)
	 * 
	 * @param newCouponCode TODO
	 */
	public void setCouponCode (final String newCouponCode) {
		// default setter (theys, Oct 28, 2009)
		couponCode = newCouponCode;
	}

	/**
	 * TODO: document this method (theys, Nov 3, 2009)
	 * 
	 * @param newCouponID TODO
	 */
	public void setCouponID (final int newCouponID) {
		// default setter (theys, Oct 28, 2009)
		couponID = newCouponID;
	}

	/**
	 * TODO: document this method (theys, Nov 3, 2009)
	 * 
	 * @param newCouponMinAmount TODO
	 */
	public void setCouponMinAmount (final BigDecimal newCouponMinAmount) {
		// default setter (theys, Oct 28, 2009)
		couponMinAmount = newCouponMinAmount;
	}

	/**
	 * TODO: document this method (theys, Nov 3, 2009)
	 * 
	 * @param newCouponName TODO
	 */
	public void setCouponName (final String newCouponName) {
		// default setter (theys, Oct 28, 2009)
		couponName = newCouponName;
	}

	/**
	 * TODO: document this method (theys, Nov 3, 2009)
	 * 
	 * @param newEndDate TODO
	 */
	public void setEndDate (final Date newEndDate) {
		// default setter (theys, Oct 28, 2009)
		endDate = newEndDate;
	}

	/**
	 * TODO: document this method (theys, Nov 3, 2009)
	 * 
	 * @param newStartDate TODO
	 */
	public void setStartDate (final Date newStartDate) {
		// default setter (theys, Oct 28, 2009)
		startDate = newStartDate;
	}

	/**
	 * TODO: document this method (theys, Nov 3, 2009)
	 * 
	 * @param newUsesPerCoupon TODO
	 */
	public void setUsesPerCoupon (final int newUsesPerCoupon) {
		// default setter (theys, Oct 28, 2009)
		usesPerCoupon = newUsesPerCoupon;
	}

	/**
	 * TODO: document this method (theys, Nov 3, 2009)
	 * 
	 * @param newUsesPerUser TODO
	 */
	public void setUsesPerUser (final int newUsesPerUser) {
		// default setter (theys, Oct 28, 2009)
		usesPerUser = newUsesPerUser;
	}

}
