/**
*    
*/

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;
  }
}