package com.atomikos.examples.tomcat.jdbc;

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

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import javax.transaction.Status;
import javax.transaction.UserTransaction;


public class AccountService {

	public long getBalance(int account) throws Exception {
		beginTransaction();
		long res = -1;
		try (Connection conn = getConnection();
			PreparedStatement ps = conn.prepareStatement("select balance from Accounts where account='account" + account + "'")){
			ResultSet rs = ps.executeQuery();
			if (rs == null || !rs.next())
				throw new Exception("Account not found: " + account);
			res = rs.getLong(1);
		} catch (Exception e) {
			rollbackTransaction();
			throw e;
		} 
		commitTransaction();
		return res;
	}


	public void withdraw(int account, int amount) throws Exception {
		beginTransaction();
		try (Connection conn = getConnection();
			PreparedStatement ps = conn.prepareStatement("update Accounts set balance = balance - " + amount+ " where account ='account" + account + "'")){
			ps.execute();
		} catch (Exception e) {
			rollbackTransaction();
			throw e;
		} 
		commitTransaction();
	}

	private void beginTransaction() throws Exception {
		// Retrieve of construct the UserTransaction
		// (can be bound in JNDI where available)
		UserTransaction utx = lookupUserTransaction();
		// First, create a transaction
		utx.begin();
	}

	
	private void commitTransaction() throws Exception {
		UserTransaction utx = lookupUserTransaction();
		if (utx.getStatus() != Status.STATUS_NO_TRANSACTION) {
			utx.commit();
		}	
	}

	private void rollbackTransaction() throws Exception {
		UserTransaction utx = lookupUserTransaction();
		if (utx.getStatus() != Status.STATUS_NO_TRANSACTION) {
			utx.rollback();
		}		
	}

	private Connection getConnection() throws Exception {
		DataSource ds = lookupDataSource();
		return ds.getConnection();

	}
	private DataSource lookupDataSource() throws NamingException {
		Context initCtx = new InitialContext();
		Context envCtx = (Context) initCtx.lookup("java:comp/env");
		DataSource ds = (DataSource) envCtx.lookup("jdbc/demodb");
		return ds;
	}

	private UserTransaction lookupUserTransaction() throws NamingException {
		Context initCtx = new InitialContext();
		Context ctx = (Context) initCtx.lookup("java:comp");
		return (UserTransaction) ctx.lookup("UserTransaction");
	}

}
