/**
*    
*/

package concurent;

/*
* Thread
*/

class Person extends Thread{
  Bank bank=null;
  int from;
  int to;
  double amount;
  public Person(Bank bank2, int i, int j, double d) {
    this.bank=bank2;
    this.from=i;
    this.to=j;
    this.amount=d;
  }

  public void run(){
    //get bank size
    System.out.println("The bank size:"+bank.size());
    //out accounts
    bank.out();
    //transfer
    try {
      bank.transfer(from, to, amount);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    //out accounts    
    bank.out();
  }
}

/**
* @author daniel    
* This case main show three thread transfer money in the same bank
*/

public class BankTest {

  /**
    * @param args
    */

  public static void main(String[] args) {
    Bank bank=new Bank(3,100.00);
    Person p1=new Person(bank,0,1,50.00);
    Person p2=new Person(bank,0,1,100.00);
    Person p3=new Person(bank,1,0,60.00);
    p1.start();
    p2.start();
    p3.start();
  }
}

/**
* Bank model
* @author daniel
*
*/

class Bank {
  private final double[] accounts;    
    
  /**
    * Constructs the bank
    * @param n
    * @param initialBalance
    */

  public Bank(int n, double initialBalance){
    accounts=new double[n];
    for(int i=0;i<accounts.length;i++){
      accounts[i]=initialBalance;        
    }
  }
    
  /**
    * Transfers money from one account to another
    * @param from
    * @param to
    * @param amount
    * @throws InterruptedException
    */

  public synchronized void transfer(int from, int to, double amount) throws InterruptedException{
    while(accounts[from]<amount)
      wait();
    System.out.println(Thread.currentThread());
    accounts[from] -=amount;
    System.out.printf("%10.2f from %d to %d",amount,from,to);
    accounts[to] +=amount;
    System.out.printf("     Total Balance: %10.2f%n", getTotalBalance());
    notifyAll();
  }

  /**
    * Gets the sum of all account balances
    * @return
    */

  public synchronized double getTotalBalance() {
    double sum =0 ;    
    for(double a : accounts){
      sum+=a;
    }
    return sum;
  }
    
  public void out(){
    for(int i=0;i<accounts.length;i++){
      System.out.println("accounts["+i+"]:"+accounts[i]);
    }
  }
  /**
    * get the number of accounts in the bank
    * @return
    */

  public int size(){
    return accounts.length;
  }
}