class CreditCardSystem {
	CreditCardSystem() {
		Account account = new Account(1000);
		new TransactionThread(account, 1000).start();
		new TransactionThread(account, 1000).start();
	}

	class TransactionThread extends Thread {
		TransactionThread(Account account, int amount) {
			this.account = account;
			this.amount = amount;
		}

		public void run() {
			if (account.fundsAvailable(amount)) {
				System.out.println(Thread.currentThread().getName() + ": Preparing for the charge");
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
				}
				account.charge(amount);

			}
		}

		Account account;
		int amount;
	}

	public static void main(String [] args) {
		new CreditCardSystem();
	}
}

class Account {
	Account(int balance) {
		this.id = nextId++;
		this.balance = balance;
		System.out.println(Thread.currentThread().getName() + ": Account #" + id + "created with an initial balance of $" + balance);
	}

	synchronized boolean fundsAvailable(int amount) {
		if (balance >= amount)
			System.out.println(Thread.currentThread().getName() + ": Account #" + id + " appears to have sufficient funds($" + balance + ") for a charge of $" + amount);
		else
			System.out.println(Thread.currentThread().getName() + ": Account #" + id + " insufficient funds($" + balance + ") for a charge of $" + amount);

		return balance >= amount;
	}

	synchronized void charge(int amount) {
		try {
			System.out.println(Thread.currentThread().getName() + ": Doing something");
			Thread.sleep(2000);
			int newBalance = balance - amount;
			Thread.sleep(2000);
			System.out.println(Thread.currentThread().getName() + ": Doing something else");
			balance = newBalance;
			System.out.println(Thread.currentThread().getName() + ": Account #" + id + " sucessfully charged $" + amount + " leaving a balance of $" + balance);
		} catch (Exception e) {
		}
	}

	int id;
	int balance;
	static int nextId = 1;
}

