// Path: src/main/java/de/calette/mephisto3/Mephisto3.java
// public class Mephisto3 extends Application {
//   public static final int WIDTH = Callete.getConfiguration().getInt("width", 700);
//   public static final int HEIGHT = Callete.getConfiguration().getInt("height", 395);
//   public static StackPane rootStack;
// 
//   public static void main(String[] args) {
//     launch(args);
//   }
// 
//   @Override
//   public void start(final Stage primaryStage) {
//     Callete.getGPIOService().setSimulationMode(SystemUtils.isWindows());
// 
//     //force rendering of small fonts
//     System.setProperty("prism.lcdtext", "false");
// 
//     //apply new image cache dir
//     if(!SystemUtils.isWindows()) {
//       AlbumCoverCache.setCacheDir(new File("../image_cache/"));
//     }
// 
//     //create root component with background
//     rootStack = new StackPane();
//     rootStack.getChildren().add(new Center());
// 
//     Scene scene = new Scene(rootStack, (double) WIDTH, (double) HEIGHT);
//     scene.getStylesheets().add(ResourceLoader.getResource("theme.css"));
//     primaryStage.setScene(scene);
//     primaryStage.getScene().setRoot(rootStack);
// 
//     primaryStage.addEventFilter(KeyEvent.KEY_PRESSED, new Mephisto3KeyEventFilter());
//     addDisposeListener(primaryStage);
// 
//     if(!SystemUtils.isWindows()) {
//       primaryStage.initStyle(StageStyle.UNDECORATED);
//     }
//     
//     int x = Callete.getConfiguration().getInt("position.x", 0);
//     int y = Callete.getConfiguration().getInt("position.y", 0);
//     if(x == 0 && y == 0) {
//       primaryStage.centerOnScreen();
//     }
//     else {
//       primaryStage.setX(x);
//       primaryStage.setY(y);
//     }
// 
//     //finally show the stage
//     primaryStage.show();    
//     
//     Center.getInstance().loadServices();
//   }
// 
//   //--------------------------- Helper --------------------------------------------
// 
//   private static void addDisposeListener(Stage primaryStage) {
//     //ensures that the process is terminated on window dispose
//     primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
//       @Override
//       public void handle(WindowEvent windowEvent) {
//         Platform.exit();
//         System.exit(0);
//       }
//     });
//   }
// }
// 
// Path: src/main/java/de/calette/mephisto3/ui/ServiceChangeListener.java
// public interface ServiceChangeListener {
// 
//   /**
//    * Fired when the service has changed, passes
//    * the new models so that the component can update.
//    */
//   void serviceChanged(ServiceState serviceState);
// }
// 
// Path: src/main/java/de/calette/mephisto3/util/Executor.java
// public class Executor {
// 
//   public static Thread run(final Runnable r) {
//     Thread t = new Thread(r);
//     t.start();
//     return t;
//   }
// }
// 
// Path: src/main/java/de/calette/mephisto3/util/NodeDebugger.java
// public class NodeDebugger {
// 
//   public static void dump(Node n) {
//     dump(n, 0);
//   }
// 
//   private static void dump(Node n, int depth) {
//     for(int i = 0; i < depth; i++) {
//       System.out.print("  ");
//     }
//     log(n);
//     if(n instanceof Parent)
//       for(Node c : ((Parent) n).getChildrenUnmodifiable())
//         dump(c, depth + 1);
//   }
// 
//   private static void log(Node n) {
//     System.out.println(n + " [visible:" + n.isVisible() + ", opacity:" + n.getOpacity() + ", class:" + n.getStyleClass() + "]");
//   }
// }


import callete.api.Callete;
import callete.api.services.Service;
import callete.api.services.ServiceModel;
import callete.api.services.gpio.*;
import callete.api.services.impl.simulator.SimulatorPushButton;
import callete.api.services.impl.simulator.SimulatorRotaryEncoder;
import callete.api.services.music.model.Stream;
import de.calette.mephisto3.Mephisto3;
import de.calette.mephisto3.ui.ServiceChangeListener;
import de.calette.mephisto3.util.Executor;
import de.calette.mephisto3.util.NodeDebugger;
import javafx.application.Platform;
import javafx.scene.input.KeyCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

  public void removeControlListener(ControlListener listener) {
    this.controlListeners.remove(listener);
  }

  /**
   * Activates the UI for the given service.
   *
   * @param service the service to activate.
   */
  public void switchService(Service service) {
    Executor.run(new Runnable() {
      @Override
      public void run() {
        if(service.equals(Callete.getWeatherService())) {
          serviceState.setService(Callete.getWeatherService());
          serviceState.setModels(Callete.getWeatherService().getWeather());
        }
        else if(service.equals(Callete.getStreamingService())) {
          serviceState.setService(Callete.getStreamingService());
          serviceState.setModels(Callete.getStreamingService().getStreams());
        }
        else if(service.equals(Callete.getGoogleMusicService())) {
          serviceState.setService(Callete.getGoogleMusicService());
          serviceState.setModels(Callete.getGoogleMusicService().getAlbums());
        }
        else if(service.equals(Callete.getSystemService())) {
          serviceState.setService(Callete.getSystemService());
          serviceState.setModels(Collections.<ServiceModel>emptyList());
        }
// Path: src/main/java/de/calette/mephisto3/Mephisto3.java
// public class Mephisto3 extends Application {
//   public static final int WIDTH = Callete.getConfiguration().getInt("width", 700);
//   public static final int HEIGHT = Callete.getConfiguration().getInt("height", 395);
//   public static StackPane rootStack;
// 
//   public static void main(String[] args) {
//     launch(args);
//   }
// 
//   @Override
//   public void start(final Stage primaryStage) {
//     Callete.getGPIOService().setSimulationMode(SystemUtils.isWindows());
// 
//     //force rendering of small fonts
//     System.setProperty("prism.lcdtext", "false");
// 
//     //apply new image cache dir
//     if(!SystemUtils.isWindows()) {
//       AlbumCoverCache.setCacheDir(new File("../image_cache/"));
//     }
// 
//     //create root component with background
//     rootStack = new StackPane();
//     rootStack.getChildren().add(new Center());
// 
//     Scene scene = new Scene(rootStack, (double) WIDTH, (double) HEIGHT);
//     scene.getStylesheets().add(ResourceLoader.getResource("theme.css"));
//     primaryStage.setScene(scene);
//     primaryStage.getScene().setRoot(rootStack);
// 
//     primaryStage.addEventFilter(KeyEvent.KEY_PRESSED, new Mephisto3KeyEventFilter());
//     addDisposeListener(primaryStage);
// 
//     if(!SystemUtils.isWindows()) {
//       primaryStage.initStyle(StageStyle.UNDECORATED);
//     }
//     
//     int x = Callete.getConfiguration().getInt("position.x", 0);
//     int y = Callete.getConfiguration().getInt("position.y", 0);
//     if(x == 0 && y == 0) {
//       primaryStage.centerOnScreen();
//     }
//     else {
//       primaryStage.setX(x);
//       primaryStage.setY(y);
//     }
// 
//     //finally show the stage
//     primaryStage.show();    
//     
//     Center.getInstance().loadServices();
//   }
// 
//   //--------------------------- Helper --------------------------------------------
// 
//   private static void addDisposeListener(Stage primaryStage) {
//     //ensures that the process is terminated on window dispose
//     primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
//       @Override
//       public void handle(WindowEvent windowEvent) {
//         Platform.exit();
//         System.exit(0);
//       }
//     });
//   }
// }
// 
// Path: src/main/java/de/calette/mephisto3/ui/ServiceChangeListener.java
// public interface ServiceChangeListener {
// 
//   /**
//    * Fired when the service has changed, passes
//    * the new models so that the component can update.
//    */
//   void serviceChanged(ServiceState serviceState);
// }
// 
// Path: src/main/java/de/calette/mephisto3/util/Executor.java
// public class Executor {
// 
//   public static Thread run(final Runnable r) {
//     Thread t = new Thread(r);
//     t.start();
//     return t;
//   }
// }
// 
// Path: src/main/java/de/calette/mephisto3/util/NodeDebugger.java
// public class NodeDebugger {
// 
//   public static void dump(Node n) {
//     dump(n, 0);
//   }
// 
//   private static void dump(Node n, int depth) {
//     for(int i = 0; i < depth; i++) {
//       System.out.print("  ");
//     }
//     log(n);
//     if(n instanceof Parent)
//       for(Node c : ((Parent) n).getChildrenUnmodifiable())
//         dump(c, depth + 1);
//   }
// 
//   private static void log(Node n) {
//     System.out.println(n + " [visible:" + n.isVisible() + ", opacity:" + n.getOpacity() + ", class:" + n.getStyleClass() + "]");
//   }
// }


// Path: src/main/java/de/calette/mephisto3/control/ServiceController.java
import callete.api.Callete;
import callete.api.services.Service;
import callete.api.services.ServiceModel;
import callete.api.services.gpio.*;
import callete.api.services.impl.simulator.SimulatorPushButton;
import callete.api.services.impl.simulator.SimulatorRotaryEncoder;
import callete.api.services.music.model.Stream;
import de.calette.mephisto3.Mephisto3;
import de.calette.mephisto3.ui.ServiceChangeListener;
import de.calette.mephisto3.util.Executor;
import de.calette.mephisto3.util.NodeDebugger;
import javafx.application.Platform;
import javafx.scene.input.KeyCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


  public void removeControlListener(ControlListener listener) {
    this.controlListeners.remove(listener);
  }

  /**
   * Activates the UI for the given service.
   *
   * @param service the service to activate.
   */
  public void switchService(Service service) {
    Executor.run(new Runnable() {
      @Override
      public void run() {
        if(service.equals(Callete.getWeatherService())) {
          serviceState.setService(Callete.getWeatherService());
          serviceState.setModels(Callete.getWeatherService().getWeather());
        }
        else if(service.equals(Callete.getStreamingService())) {
          serviceState.setService(Callete.getStreamingService());
          serviceState.setModels(Callete.getStreamingService().getStreams());
        }
        else if(service.equals(Callete.getGoogleMusicService())) {
          serviceState.setService(Callete.getGoogleMusicService());
          serviceState.setModels(Callete.getGoogleMusicService().getAlbums());
        }
        else if(service.equals(Callete.getSystemService())) {
          serviceState.setService(Callete.getSystemService());
          serviceState.setModels(Collections.<ServiceModel>emptyList());
        }
        else if(service.equals(Callete.getNetworkMusicService())) {