/*
 * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

/*
 * $Id$
 */

package ee.jakarta.tck.persistence.ee.propagation.cm.jta;


import com.sun.ts.lib.util.TestUtil;
import ee.jakarta.tck.persistence.ee.common.Account;
import jakarta.annotation.Resource;
import jakarta.ejb.EJBException;
import jakarta.ejb.Local;
import jakarta.ejb.SessionContext;
import jakarta.ejb.Stateful;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.PersistenceContextType;

import java.util.Iterator;
import java.util.List;

@Stateful(name = "TellerBean")
@Local({ Teller.class })
public class TellerBean implements Teller {

	

	public SessionContext sessionContext;

	// instance variables
	private static final int ACCOUNTS[] = { 1000, 1075, 40, 30564, 387 };

	private static final double BALANCES[] = { 50000.0, 10490.75, 200.50, 25000.0, 1000000.0 };

	private Account accountRef;

	// ===========================================================
	// Initialize Bean

	@PersistenceContext(unitName = "CTS-JTA-UNIT", type = PersistenceContextType.TRANSACTION)
	private EntityManager entityManager;

	@Resource
	public void setSessionContext(SessionContext sessionContext) {
		this.sessionContext = sessionContext;
	}

	// ===========================================================
	// Teller interface (our business methods)

	public double balance(final int acct) {
		TestUtil.logTrace( "balance");
		Account thisAccount = entityManager.find(Account.class, acct);
		double balance;
		try {
			balance = thisAccount.balance();
		} catch (Exception e) {
			TestUtil.printStackTrace(e);
			throw new EJBException("Exception occurred in balance: " + e);
		}
		return balance;
	}

	public double deposit(final int acct, final double amt) {
		TestUtil.logTrace( "deposit");
		double balance;
		Account thisAccount = entityManager.find(Account.class, acct);
		try {
			balance = thisAccount.deposit(amt);
		} catch (Exception e) {
			TestUtil.printStackTrace(e);
			throw new EJBException("Exception occurred in deposit: " + e);
		}
		return balance;
	}

	public double withdraw(final int acct, final double amt) {
		TestUtil.logTrace( "withdraw");
		double balance;
		Account thisAccount = entityManager.find(Account.class, acct);
		try {
			balance = thisAccount.withdraw(amt);
		} catch (Exception e) {
			TestUtil.printStackTrace(e);
			throw new EJBException("Exception occurred in withdraw: " + e);
		}
		return balance;
	}

	public boolean checkAccountStatus(final Account acct) {
		TestUtil.logTrace( "checkAccountStatus");
		Account thisAccount = entityManager.find(Account.class, acct.id());

		if (acct.equals(thisAccount)) {
			return true;
		} else {
			return false;
		}
	}

	public String getAllAccounts() {
		StringBuffer accounts = new StringBuffer();
		List result = null;
		try {
			result = entityManager.createQuery("select a from Account a").getResultList();

			Iterator i = result.iterator();
			while (i.hasNext()) {
				Account a1 = (Account) i.next();
				accounts.append("" + a1.id() + "  " + (double) a1.balance() + "\n");
			}

		} catch (Exception e) {
			TestUtil.printStackTrace(e);
			throw new EJBException("Exception occurred in getAllAccounts: " + e);
		}
		return accounts.toString();
	}

	// ===========================================================
	// Helpers

	public void createTestData() {
		try {

			TestUtil.logTrace( "createAccountData");

			TestUtil.logTrace( "Create " + ACCOUNTS.length + " Account Entities");
			System.out.println("Create " + ACCOUNTS.length + " Account Entities");

			for (int i = 0; i < ACCOUNTS.length; i++) {
				TestUtil.logTrace( "Creating account=" + ACCOUNTS[i] + ", balance=" + BALANCES[i]);
				System.out.println("Creating account=" + ACCOUNTS[i] + ", balance=" + BALANCES[i]);
				accountRef = new Account(ACCOUNTS[i], BALANCES[i]);
				System.out.println("Persisting Account:" + accountRef);
				entityManager.persist(accountRef);

			}
		} catch (Exception e) {
			TestUtil.logErr( "Unexpected while creating test data:" + e);
		}
	}

	public void removeTestData() {
		TestUtil.logTrace( "removeTestData");
		try {
			entityManager.createNativeQuery("DELETE FROM ACCOUNT").executeUpdate();
		} catch (Exception e) {
			TestUtil.logErr( "Exception encountered while removing entities:", e);
		}
		// clear the cache if the provider supports caching otherwise
		// the evictAll is ignored.
		TestUtil.logTrace( "Clearing cache");
		entityManager.getEntityManagerFactory().getCache().evictAll();
	}

}
