content: package com.gc.fakeimagedetection.ui.controllers;
  
  import com.jfoenix.controls.JFXButton;
  import com.jfoenix.controls.JFXSnackbar;
  import com.gc.fakeimagedetection.core.constants.ConstantObjects;
  import com.gc.fakeimagedetection.core.errorlevelanalysis.FIDErrorLevelAnalysis;
  import com.gc.fakeimagedetection.core.listener.ErrorLevelAnalysisListener;
  import com.gc.fakeimagedetection.core.listener.NeuralnetProcessorListener;
  import com.gc.fakeimagedetection.core.metadata.MetadataProcessor;
  import com.gc.fakeimagedetection.core.processor.NeuralNetProcessor;
  import com.gc.fakeimagedetection.core.trainer.SingleImageTrainer;
  import com.gc.fakeimagedetection.core.listener.ThreadCompleteListener;
  import com.gc.fakeimagedetection.ui.alert.Calert;
  import ij.ImagePlus;
  import java.awt.Dimension;
  import java.awt.image.BufferedImage;
  import java.io.IOException;
  import java.net.URL;
  import java.text.DecimalFormat;
  import java.util.HashMap;
  import java.util.Optional;
  import java.util.ResourceBundle;
  import java.util.logging.Level;
  import java.util.logging.Logger;
  import javafx.animation.KeyFrame;
  import javafx.animation.KeyValue;
  import javafx.animation.ParallelTransition;
  import javafx.animation.ScaleTransition;
  import javafx.animation.Timeline;
  import javafx.animation.TranslateTransition;
  import javafx.application.Platform;
  import javafx.event.Event;
  import javafx.event.EventHandler;
  import javafx.fxml.FXML;
  import javafx.fxml.FXMLLoader;
  import javafx.fxml.Initializable;
  import javafx.scene.Scene;
  import javafx.scene.control.Alert;
  import javafx.scene.control.Alert.AlertType;
  import javafx.scene.control.ButtonBar.ButtonData;
  import javafx.scene.control.ButtonType;
  import javafx.scene.image.ImageView;
  import javafx.scene.input.MouseButton;
  import javafx.scene.input.MouseEvent;
  import javafx.scene.layout.AnchorPane;
  import javafx.scene.layout.StackPane;
  import javafx.scene.text.Text;
  import javafx.stage.Stage;
  import javafx.util.Duration;
  import javax.imageio.ImageIO;
  
  public class NeuralnetInterfaceController implements
          Initializable, ErrorLevelAnalysisListener, ThreadCompleteListener, NeuralnetProcessorListener {
  
      public static String imageLocation = "";
  
      public static String getImageLocation() {
          return imageLocation = LaunchScreeenController.processingFile.getAbsolutePath();
      }
  
      @FXML
      private StackPane rootPane;
      @FXML
      private ImageView backgroundImageView;
      @FXML
      private AnchorPane anchorPane;
      @FXML
      private Text description;
      @FXML
      private Text christopher;
      @FXML
      private JFXButton navigation_button;
      @FXML
      private ImageView homeIcon;
  
      NeuralnetInterfaceController thisObject = this;
      ScaleTransition bulgingTransition;
      FIDErrorLevelAnalysis elaAnalyzer;
      NeuralNetProcessor nprocessor;
      BufferedImage elaImage;
  
      @Override
      public void initialize(URL url, ResourceBundle rb) {
          startAnimation();
          getImageLocation();
  
          elaAnalyzer = new FIDErrorLevelAnalysis(imageLocation, 95, new Dimension(100, 100), this);
          elaAnalyzer.setName("elaAnalyzer");
          elaAnalyzer.start();
  
      }
  
      private void startAnimation() {
          navigation_button.setText("Applying ELA on Image");
          float animationExtension = 1.2f;
          bulgingTransition = new ScaleTransition(Duration.millis(2000), navigation_button);
          bulgingTransition.setToX(animationExtension);
          bulgingTransition.setToY(animationExtension);
          bulgingTransition.autoReverseProperty().setValue(true);
          bulgingTransition.setCycleCount(bulgingTransition.INDEFINITE);
          bulgingTransition.play();
      }
  
      @FXML
      private void loadAnimation(MouseEvent event) {
      }
  
      @FXML
      private void rollBack(MouseEvent event) {
          LaunchScreeenController.processingFile = null;
          MetadataProcessor.extracted_data = "";
          try {
              Stage stage = (Stage) rootPane.getScene().getWindow();
              Scene pane = new Scene(FXMLLoader.load(getClass().getResource("/resources/fxml/launch.fxml")));
              stage.setScene(pane);
          } catch (IOException ex) {
              Logger.getLogger(NeuralnetInterfaceController.class.getName()).log(Level.SEVERE, null, ex);
          }
      }
  
      void updateIndicatorText(String message) {
          Platform.runLater(new Runnable() {
              @Override
              public void run() {
                  navigation_button.setText(message);
              }
          });
      }
  
      void finalMoveOfIndicator() {
          Platform.runLater(new Runnable() {
              @Override
              public void run() {
                  Timeline timeline = new Timeline();
                  timeline.setCycleCount(1);
  
                  KeyValue keyValueX = new KeyValue(navigation_button.prefWidthProperty(), 300);
                  KeyFrame keyFrame = new KeyFrame(Duration.millis(2000), keyValueX);
                  timeline.getKeyFrames().add(keyFrame);
  
                  timeline.play();
                  navigation_button.setStyle("-fx-background-radius: 0px;");
              }
          });
      }
  
      void loadResult(HashMap<String, Double> result) {
          System.out.println("Metadata Result: Fakeness = " + ConstantObjects.fakeness);
          if (ConstantObjects.fakeness < 0) {
              System.out.println("Invalid Result from metadata");
          }
  
          Platform.runLater(new Runnable() {
              final float NEURAL_NET_WEIGHT = 0.4f;
              final float METADATA_NET_WEIGHT = 1-NEURAL_NET_WEIGHT;
  
              @Override
              public void run() {
                  double real = result.get("real") * 100;
                  double fake = result.get("faked") * 100;
  
                  DecimalFormat df2 = new DecimalFormat(".#");
                  if (ConstantObjects.shouldPropogateResult) {
                      real = (real*NEURAL_NET_WEIGHT) + (METADATA_NET_WEIGHT * ConstantObjects.realness*100);
                      fake = (fake*NEURAL_NET_WEIGHT) + (METADATA_NET_WEIGHT * ConstantObjects.fakeness*100);
                  }
  
                  if (real < 10 && fake < 10) {
                      String possibility;
                      if (real >= fake) {
                          possibility = "Possibly Real";
                      } else {
                          possibility = "Possibly Fake";
                      }
                      navigation_button.setStyle("-fx-background-color:#EF6C00");
                      navigation_button.setText("Cant Determine whether fake or not " + possibility);
  
                  } else if (fake > real) {
                      navigation_button.setStyle("-fx-background-color:#f44336");
                      navigation_button.setText("FAKE IMAGE" + "\nConfidence :" + df2.format(fake) + "%");
                  } else if (fake < real) {
                      navigation_button.setStyle("-fx-background-color:#4CAF50");
                      navigation_button.setText("REAL IMAGE" + "\nConfidence :" + df2.format(real) + "%");
                  } else {
                      navigation_button.setStyle("-fx-background-color:#4CAF50");
                      navigation_button.setText("Process Failed. 50-50 Chance");
                  }
  
                  final JFXSnackbar snackbar = new JFXSnackbar(rootPane);
                  snackbar.getStylesheets().add(getClass().getResource("/resources/stylesheets/main.css").toExternalForm());
                  EventHandler handler = new EventHandler() {
                      @Override
                      public void handle(Event event) {
                          snackbar.unregisterSnackbarContainer(rootPane);
                          Alert alert = new Alert(AlertType.CONFIRMATION);
                          alert.setTitle("Confirmation Dialog");
                          alert.setContentText("Is this image Fake or Real ?");
  
                          ButtonType fakeButton = new ButtonType("Fake");
                          ButtonType realButton = new ButtonType("Real");
                          ButtonType buttonTypeCancel = new ButtonType("Cancel", ButtonData.CANCEL_CLOSE);
  
                          alert.getButtonTypes().setAll(fakeButton, realButton, buttonTypeCancel);
  
                          Optional<ButtonType> result = alert.showAndWait();
                          if (result.get() == fakeButton) {
                              navigation_button.setText("Learning...");
                              SingleImageTrainer learner
                                      = new SingleImageTrainer(NeuralNetProcessor.nnet, elaImage, false);
                              learner.addListener(thisObject);
                              learner.setName("learner");
                              learner.start();
                          } else if (result.get() == realButton) {
                              navigation_button.setText("Learning...");
                              SingleImageTrainer learner
                                      = new SingleImageTrainer(NeuralNetProcessor.nnet, elaImage, true);
                              learner.addListener(thisObject);
                              learner.setName("learner");
                              learner.start();
                          } else {
  
                          }
                      }
                  };
                  snackbar.show("Isn't That Right ? Help Me Grow", "Okay", 10000, handler);
  
                  addELAListener();
              }
  
              private void addELAListener() {
                  navigation_button.setOnAction((e) -> {
                  });
  
                  navigation_button.setOnMousePressed(new EventHandler<MouseEvent>() {
                      @Override
                      public void handle(MouseEvent event) {
                          if (event.getButton() == MouseButton.PRIMARY) {
                              new ImagePlus("Error Level Analysis", elaImage).show();
                          } else if (event.getButton() == MouseButton.SECONDARY) {
                              try {
                                  new ImagePlus("Original Image", ImageIO.read(LaunchScreeenController.processingFile)).show();
                              } catch (IOException ex) {
                                  Logger.getLogger(NeuralnetInterfaceController.class.getName()).log(Level.SEVERE, null, ex);
                              }
                          }
                      }
                  });
              }
          });
      }
  
      private void removeBannersandDescs() {
          TranslateTransition tChristopher = new TranslateTransition(Duration.millis(1000), christopher);
          TranslateTransition tDescription = new TranslateTransition(Duration.millis(1000), description);
          tChristopher.setToY(-500);
          tDescription.setToY(-500);
          ParallelTransition pt = new ParallelTransition(tChristopher, tDescription);
          pt.play();
  
      }
  
      @Override
      public void notifyOfThreadComplete(Thread thread) {
          switch (thread.getName()) {
              case "learner":
                  updateIndicatorText("Learning Complete");
                  break;
          }
      }
  
      @Override
      public void elaCompleted(BufferedImage image) {
          updateIndicatorText("Serializing Image");
          elaImage = image;
          updateIndicatorText("Connecting to Neural Network");
          nprocessor = new NeuralNetProcessor(elaImage);
          nprocessor.setName("nprocessor");
          nprocessor.addListener(this);
          nprocessor.setListener(this);
          nprocessor.start();
          removeBannersandDescs();
      }
  
      @Override
      public void neuralnetProcessCompleted(HashMap<String, Double> result) {
          if (result == null) {
              Platform.runLater(new Runnable() {
                  @Override
                  public void run() {
                      Calert.showAlert("Forced Rollback", "Image Detection Failed:\nCorrupted File", AlertType.ERROR);
                      rollBack(null);
                      return;
                  }
              });
          }
          bulgingTransition.stop();
          updateIndicatorText("Done");
          System.out.println("Neural net result:-\n" + result);
          loadResult(result);
      }
  }
  