from flask import Flask, render_template, request, url_for, redirect, flash, session
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.babel import Babel, gettext
from mailsnake import MailSnake
import sys, os, datetime
import short_url


def static(filename):
	"""Provides the 'static' function that also appends the file's timestamp to the URL, usable in a template."""
	timestamp = os.path.getmtime(os.path.join(app.static_folder, filename))
	return "%s/%s?%s" % (app.static_url_path, filename, timestamp)

app = Flask(__name__)
app.config.from_object('settings_production')
app.static_url_path = app.config["STATIC_URL"]
app.jinja_env.globals.update(static=static)

db = SQLAlchemy(app)
babel = Babel(app)
ms = MailSnake(app.config["MAILCHIMP_API_KEY"])

mailchimp_subscriber = {"id": app.config["MAILCHIMP_LIST_ID"],
						"email_address": "",
						"double_optin": False,
						"send_welcome": True
						}

# Beta user db
class BetaUser(db.Model):
	__tablename__ = "beta_user"
	id = db.Column(db.Integer, primary_key=True)
	email = db.Column(db.String(120), unique=True)
	registered_date = db.Column(db.DateTime, index=True)
	recommend_times = db.Column(db.Integer(), default=0)
	recommended_from = db.Column(db.String(120), default="")
	shorten_url = db.Column(db.String(120))

try:
	db.create_all()
except Exception, e:
	raise e

# Helpers
def add_beta_user(email, shorten_url, recommended_from):
	beta_user = BetaUser()
	beta_user.email = email
	beta_user.registered_date = datetime.datetime.now()
	beta_user.recommended_from = recommended_from
	beta_user.shorten_url = shorten_url

	db.session.add(beta_user)
	db.session.commit()

def _main(shorten_url):

	if request.method == "GET":
		return render_template("index.html")
	else:
		recommended_from = ""

		if 'promo_link' in session:
			recommended_user = db.session.query(BetaUser).filter_by(shorten_url=session['promo_link']).one()
			recommended_from = recommended_user.email
			recommended_user.recommend_times += 1
			db.session.commit()
			session.pop('promo_link')

		email = request.form.get("email")
		mailchimp_subscriber["email_address"] = email

		# Subscribe email address to Mailchimp Beta List,
		# API Doc: http://apidocs.mailchimp.com/api/rtfm/listsubscribe.func.php
		try:
			if ms.listSubscribe(**mailchimp_subscriber):
				# Get current user id
				count = db.session.query(BetaUser).count() + 1
				# Generate short url
				s_url = short_url.encode_url(count)
				add_beta_user(email, s_url, recommended_from)
				session['shorten_url'] = s_url
		except Exception, e:
			# Get exception type: exc_type from sys.exc_info()
			exc_type, exc_obj, exc_tb = sys.exc_info()
			# Check to see if this email has been registered in Mailchimp
			# Then display i18n error message from Flask-Babel: gettext
			if app.config["MAILCHIMP_EXCEPTION_LIST_ALREADY_SUBSCRIBED"] in str(exc_type):
				flash(gettext("Email has been registered!"))
			elif app.config["MAILCHIMP_EXCEPTION_INVALID_EMAIL"] in str(exc_type):
				flash(gettext("Invalid email format."))
			else:
				raise e
				# flash("Something wrong here!")
			return redirect(url_for("main"))

		return redirect(url_for("interested"))

# Routers
@app.route('/', methods=["GET", "POST"])
def main():
	return _main(shorten_url=None)

@app.route('/<shorten_url>', methods=["GET", "POST"])
def main_with_incentive(shorten_url):
	try:
		recommended_user = db.session.query(BetaUser).filter_by(shorten_url=shorten_url).one()
	except Exception:
		return redirect(url_for("main"))
	# Save the shorten_url to session
	session['promo_link'] = shorten_url
	return _main(shorten_url)

@app.route('/interested')
def interested():
	if 'shorten_url' in session:
		incentive_url = "http://zuipindao.com/%s" % session['shorten_url']
		session.pop('shorten_url')
		return render_template("interested.html", url=incentive_url)
	else:
		return redirect(url_for("main"))
		# return render_template("interested.html", url="http://zuipindao.com/ABCDE")

@app.errorhandler(404)
def page_not_found(error):
    return render_template('404.html'), 404

if __name__ == "__main__":
	app.run()