import java.awt.*;
import java.awt.event.*;

public class Banker extends Frame{
  
  int capital, available, clients, currentClient;
  int[] max, granted, need;
  
  public Banker(int startCapital, int numClients){
    capital = startCapital;
    available = capital;
    clients = numClients;
    currentClient=-1;
    max     = new int[clients];
    granted = new int[clients];
    need    = new int[clients];    
    for(int i = 0; i<clients;i++){
      max[i]=0;
      granted[i]=0;
      need[i]=0;
    }
    setUp();
  }

  public void startCreditLine(int x, int client){
    max[client]=x;
    need[client]=x;
  }
  
  private boolean safe(){
    boolean[] finished = new boolean[clients];
    int workingCapital = available;
    int candidate = 0;
    
    // if what he asked for is enough for him to be satisfied, 
    // we can just wait for him to finish and return what he has
    // so it is safe. 

    if(need[currentClient]==0) return true;    
    
    if(need[currentClient]<0){
      System.out.println("The banker cannot give you more than what remains for your max");
      return false;
    }
    
    if (workingCapital<0){
      System.out.println("The banker cannot give you more than what he has available");
      return false;
    }

    for(int i = 0; i<clients; i++) 
      finished[i]=false;

    candidate = nextCandidate(finished,workingCapital);
    while (candidate<clients){
      // a candidate we can treat!
      // he can finish and we can get back what he had.
      finished[candidate]=true;
      workingCapital = workingCapital + need[candidate];
      candidate=nextCandidate(finished,workingCapital);
    }    
    return (allSatisfied(finished));
  }
  
  private int nextCandidate(boolean[] f, int wc){
    for(int i = 0; i<f.length; i++){
      if (f[i]==false && need[i]<=wc){
	return i;
      }
    }
    return f.length;
  }

  private boolean allSatisfied(boolean[] f){
    for(int i=0; i<f.length; i++)
      if (!f[i]) return false;
    return true;
  }


  private void grant(int x, int client){
    granted[client]=granted[client]+x;
    available = available -x;
    need[client]=need[client]-x;
  }

  private void setUp(){
    TextField client, credit;
    Label cl,cr;
    Panel p,q;
    client=new TextField(10); 
    credit= new TextField(10);
    cl = new Label("Client  :   ");
    cr = new Label("Requires:  ");
    p=new Panel();
    q=new Panel();
    p.add(cl);
    p.add(client);
    q.add(cr);
    q.add(credit);
    add("North",p);
    add("South",q);
    pack();
    client.addActionListener(new ClientListener());
    credit.addActionListener(new CreditListener());
  }

  private class ClientListener implements ActionListener{
    public void actionPerformed(ActionEvent e){
      try{
	currentClient = Integer.parseInt(e.getActionCommand());
	System.out.println("client    :  "+currentClient);
	System.out.println("max       :  "+max[currentClient]);
	System.out.println("granted   :  "+granted[currentClient]);
	System.out.println("need      :  "+need[currentClient]);
	System.out.println("available :  "+available);
      }catch (NumberFormatException ne) {}
    }
  }

  private class CreditListener implements ActionListener{
    public void actionPerformed(ActionEvent e){
      int ammount;
      try{
	ammount = Integer.parseInt(e.getActionCommand());
	grant(ammount,currentClient);
	if (!safe()){
	  grant(-ammount,currentClient);
	  System.out.println("not granted "+ ammount);
	  System.out.println("available :  "+available);	  
	}
	else{
	  System.out.println("granted " + ammount + " to client " + currentClient);
	  System.out.println("available :  "+available);
	}
	
      }catch (NumberFormatException ne) {}
    }
  }
}
