/**  
 *  Exemplo de comunicacao entre threads Java.
 *  Adaptado de: http://www.javapractices.com/topic/TopicAction.do?Id=51
 */

class Airplane implements Runnable {
    
    private Airport fAirport;
    private String fFlightId;

    public Airplane(Airport aAirport, String aFlightId) {
        fAirport = aAirport;
        fFlightId = aFlightId;
    }
    
    public void run() {
        takeOff();
        fly();
        land();
    }
    
    private void takeOff() {
        System.out.println(fFlightId + ": esperando pista..." );
        // Espera uma pista livre
        fAirport.waitAvailableRunway();
        System.out.println(fFlightId + ": decolando...");
        
    }
    
    private void fly() {
        System.out.println(fFlightId + ": voando...");
        try {
            // Aguarda cerca de 10s
            Thread.sleep(10000);
        } catch (InterruptedException e){
            System.err.println(e);
        }
    }
    
    private void land() {
        System.out.println(fFlightId + ": esperando pista..." );
        // Espera uma pista livre
        fAirport.waitAvailableRunway();
        System.out.println(fFlightId + ": aterissando...");
    }
    
}


class Airport implements Runnable {

    private boolean fHasAvailableRunway = true;
    private String fName;
    
    public Airport(String aName) {
        fName = aName;
    }

    public synchronized void waitAvailableRunway() {
       // preencher aqui
    }
    
    public synchronized void toggleRunwayState() {
        // Inverte o estado da pista.
        fHasAvailableRunway = !fHasAvailableRunway;
        System.out.println(fName 
                           + " tem pista disponivel: " 
                           + fHasAvailableRunway);
        // Notifica a mudanca de estado para quem estiver esperando.
        this.notifyAll();
    }
    
    public void run() {
        System.out.println("Rodando aeroporto  " + fName);
        while (true) {
            try {
                toggleRunwayState();
                Thread.sleep(1000);
            } catch (InterruptedException e){
                System.err.println(e);
            }
        }
    }
}


/**  Simulador de voo com threads. */
public final class FlightSimulator {
    
    public static void main(String[] args) {
        System.out.println("Rodando simulador de voo.");
        
        // Constroi aeroporto e inicia sua execucao.
        Airport charlesDeGaulle = new Airport("Charles de Gaulle");
        Thread airport = new Thread(charlesDeGaulle);
        airport.start();
        
        // Constroi aviao e inicia sua execucao.
        Thread planeOne = new Thread(new Airplane(charlesDeGaulle, "Voo 8875"));
        planeOne.start();
        
        // Termina thread principal e deixa as demais rodando.
        System.out.println("Terminando thread principal.");
    }
}
