generate Java;
namespace aviationcontrolsystem;

//interface Personnel {
//}

class AviationControlSystem {
    public static void main(String[] args) {
        System.out.println("Initializing Aviation Control System Simulation");
        AviationControlSystem acs = new AviationControlSystem();
        
        acs.addAirport(new Airport("Here Name", "Here Place", 5, acs));
        acs.addAirport(new Airport("There Name", "There Place", 5, acs));

        //Plane plane = new Plane("Nowhere", "7057", 100.0, acs.getAirport(0));
        
        System.out.println("End Simulation");
    }
    1 -- * Airport;
}

class Airport {
    1 -- 1 AirTrafficControl;
    1 -- 1..* Runway;
    immutable name;
    immutable address;
    lazy boolean isEmergency;
}

class AirTrafficControl {
    int timeout;
    public boolean getClearance() {
        if(this.getAirport().getIsEmergency()) {
            return false;
        }
        //TODO
        return false;
    }
}

class Baggage {
  sm {
    Open {
        -> Closed;
    }
    Closed {
    }
  }
}

class Passenger {
    1 -- * Baggage;
    name;
    int age;
}

class AirCrew {
}

class GroundCrew {
}

class Plane {
    1 -- * FlightPlan;
    1 -- 2..* AirCrew;
    1 -- * Passenger;
    airline;
    flightNumber;
    callsign;
    double fuel;
    // TODO AirTrafficControl.getClearance()
    lazy boolean isCleared;
    lazy boolean hasIce;
      Flight {
        Standby {
            entry / {
                System.out.println(this.getFlightFullName());
            }
            -> FlightPrep;
        }
        FlightPrep {
            entry / {
                System.out.println(this.getFlightFullName());
            }
            isFlightReady() -> Board;
        }
        Board {
            entry / {
                System.out.println(this.getFlightFullName());
            }
            -> TakeoffPrep;
        }
        TakeoffPrep {
            -> TakeoffPipeline;
        }
        TakeoffPipeline {
            entry / {
                System.out.println(this.getFlightFullName());
            }
            Standby {
                [hasIce] -> DeIce;
            }
            DeIce {
                // 15 minutes
                after(15*60) [hasIce] -> DeIce;
            }
            takeoff() [isCleared] -> Transit;
            takeoff() [!isCleared] -> TakeoffPrep;
            //after(this.getAirport(0).getAirTrafficControl().getTimeout()) -> Standby;
        }
        Transit {
            entry / {
                System.out.println(this.getFlightFullName());
            }
            -> LandingPipeline;
        }
        LandingPipeline {
            entry / {
                System.out.println(this.getFlightFullName());
            }
            land() [isCleared] -> Disembark;
        }
        Disembark {
            entry / {
                System.out.println(this.getFlightFullName());
            }
            //-> Standby;
        }
    }
}

class Runway {
    1..* -- * GroundCrew;
    int capacity;
    status {
        Open {
            Free {
                -> Occupied;
            }
            Occupied {
            }
        }
        Closed {
            Emergency {
                -> ReadyToOpen;
            }
            Maintenance {
                -> ReadyToOpen;
            }
            ReadyToOpen {
            }
        }
    }
    direction {
        North {
            -> South;
        }
        South {
            -> North;
        }
        East {
            -> West;
        }
        West {
            -> East;
        }
    }
    //  * -> * Personnel;
}

class FlightPlan {
    * -- 2..* Airport;
    Airport origin;
    Airport destination;
}
