/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package Vue;

import Bluetooth.BluetoothManager;
import Bluetooth.BluetoothThread;
import Interfaces.Observable;
import Interfaces.Observer;
import Util.CalendarUtil;
import java.io.IOException;
import java.net.URL;
import java.text.NumberFormat;
import java.util.Calendar;
import java.util.Formatter;
import java.util.Locale;
import java.util.ResourceBundle;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.Slider;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;

/**
 * FXML Controller class
 *
 * @author invite
 */
public class FXMLVueController implements Initializable, Observer {
    //Page d'accueil
    @FXML
    private GridPane accueil;
    @FXML
    private Label temperature;
    @FXML
    private Label intensity;
    @FXML
    private Label humidityAir;
    @FXML
    private Label humidityPlante;
    @FXML
    private Label humiditySeuil;
    @FXML
    private HBox planteHydrate;
    @FXML
    private HBox urgentArrosage;
    
    //Page de configuration
    @FXML
    private GridPane configuration;
    @FXML
    private Slider seuil;
    @FXML
    private Label seuilError;
    @FXML
    private CheckBox arrosageAuto;
    @FXML
    private Button buttonBluetooth;
    @FXML
    private Label activationMessage;
    
    //Page de graphes
    @FXML
    private GridPane data;
    @FXML
    private LineChart<Number, Number> graph;
    @FXML
    private ToggleGroup granulation;
    @FXML
    private ComboBox<String> dataGraph;
    @FXML
    private NumberAxis axisYGraph;
    @FXML
    private CategoryAxis axisXGraph;
    @FXML
    private RadioButton dayGranulation;
    @FXML
    private RadioButton weekGranulation;
    @FXML
    private RadioButton monthGranulation;
    
    //Barre de menu avec les boutons
    @FXML
    private Button buttonData;
    @FXML
    private Button buttonAccueil;
    @FXML
    private Button buttonConfig;
            
    private GridPane currentGridPane;
    private Button currentButton;
    private boolean alert;
    private boolean isConnected = false;
    private BluetoothManager bluetoothManager;
    private BluetoothThread workingThread;

    
    /**
     * Initializes the controller class.
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        bluetoothManager = new BluetoothManager(this);
        alert = false;
        
        //Put the gridPane Accueil visible
        currentGridPane = accueil;
        currentButton = buttonAccueil;
        openPage(accueil, buttonAccueil);

        seuil.valueProperty().addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> obs, Number oldVal, Number newVal) {
                int intVal = ((int) Math.round(newVal.doubleValue())/10)*10;
                int intOld = ((int) Math.round(oldVal.doubleValue())/10)*10;
                seuil.setValue(intVal);
                humiditySeuil.setText(""+intVal);
                
                if(humidityPlante.getText() != null && intVal <= Integer.parseInt(humidityPlante.getText()) && intOld > Integer.parseInt(humidityPlante.getText())){ // STOP
                    boolean tmp = true;
                    changeImagePlante(false);
                    while(tmp){
                        try{
                            System.out.println("STOP");
                            workingThread.sendInstruction("STOP");
                            tmp = false;              
                        } catch(IOException e){
                            e.printStackTrace();
                          }    
                    }
                } else if(intVal > Integer.parseInt(humidityPlante.getText())){
                    work();
                    changeImagePlante(true);
                    
                }
            }
        });
        
        //Bind the label for the senewValueuil in Accueil and the value in configurations
        //humiditySeuil.textProperty().bind(Bindings.convert(seuil.valueProperty()));
        
        humidityPlante.textProperty().addListener(new ChangeListener<String>() {
            @Override
            public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                System.out.println(oldValue);
                System.out.println(newValue);
                if (oldValue != null && newValue != null && humiditySeuil.getText() != null && Integer.parseInt(newValue) < Integer.parseInt(humiditySeuil.getText())) {
                    changeImagePlante(true);
                    alert = true;
                    if(Integer.parseInt(oldValue) >  Integer.parseInt(humiditySeuil.getText())){
                        work();
                    }
                }
                else {
                    if(alert){
                        changeImagePlante(false);
                    }          
                    boolean tmp = true;
                    while(tmp){
                        try{
                            System.out.println("STOP");
                            workingThread.sendInstruction("STOP");
                            tmp = false;              
                        } catch(IOException e){
                            e.printStackTrace();
                            }    
                    }
                }
            }        
        });
        
        //Graph
        axisYGraph.setLabel("données");
        axisXGraph.setLabel("temps");
        XYChart.Series serieLine = new XYChart.Series();
        serieLine.getData().add(new XYChart.Data<>(14+"", 12));
        graph.getData().add(serieLine);
        graph.setLegendVisible(false);
        
      
    }    

    /**
     * Change the text for activate or desactivate according to the checkbox
     * @param event 
     */
    @FXML
    private void clickAuto(ActionEvent event) {
        if(arrosageAuto.isSelected()){
            arrosageAuto.setText("Activé");
        }
        else arrosageAuto.setText("Désactivé");
    }

    /**
     * Button to activate the bluetooth
     * @param event 
     */
    @FXML
    private void clickActivationBluetooth(ActionEvent event) {
        if(!this.isConnected){
           isConnected =  bluetoothManager.launch();
        }
        
        if(isConnected){
            try {
                bluetoothManager.startThread();
                this.workingThread = bluetoothManager.getWorkingThread();
                this.activationMessage.setText("Connection bluetooth activée");
                this.activationMessage.setStyle("-fx-background-color: #7fca5eff");
                this.buttonBluetooth.setDisable(true);
            } catch (Exception ex) {
                ex.printStackTrace();
            }     
        }
    }
    
    /**
     * 
     * @param obs 
     */
    @Override
    public void update(Observable obs) {
        if(obs instanceof BluetoothThread && ((BluetoothThread) obs).equals(this.workingThread)){
            BluetoothThread t = (BluetoothThread) obs;
            String[] values = t.getBuffer().split(";");    
            
            Platform.runLater(
                () -> {                    
                    this.humidityAir.setText(values[0].replaceFirst("^0+(?!$)", ""));
                    this.intensity.setText(values[1].replaceFirst("^0+(?!$)", ""));
                    this.temperature.setText(values[2].replaceFirst("^0+(?!$)", ""));
                    this.humidityPlante.setText(values[3].replaceFirst("^0+(?!$)", ""));
                }
            );
        }
    }
    
    /**
     * Update the view with the right image of the plant
     * @param alertM 
     */
    public void changeImagePlante(boolean alertM){
        if(alertM){
            this.planteHydrate.setVisible(false);
            this.urgentArrosage.setVisible(true);
        }
        else{
            this.urgentArrosage.setVisible(false);
            this.planteHydrate.setVisible(true);
        }
    }

    /**
     * Change the page for the grah page when clicking on data button
     * @param event 
     */
    @FXML
    private void clickData(ActionEvent event) {
        openPage(data, buttonData);
    }
    
    /**
     * Change the page for the accueil page when clicking on accueil button
     * @param event 
     */
    @FXML
    private void clickAccueil(ActionEvent event) {
        openPage(accueil, buttonAccueil);
    }

    /**
     * Change the page for the configuration page when clicking on configuration button
     * @param event 
     */
    @FXML
    private void clickConfig(ActionEvent event) {
       openPage(configuration, buttonConfig);
    }
    
    private void openPage(GridPane open, Button justClicked){
        currentGridPane.setVisible(false);
        open.setVisible(true);
        currentGridPane = open;
        currentButton.setStyle("-fx-background-color: #d5d5d5ff");
        currentButton = justClicked;
        currentButton.setStyle("-fx-background-color: #7fca5eff");
    }
    
    private void work(){
        if(CalendarUtil.isBusinessDay(Calendar.getInstance())){
            System.out.println("is business");
            // compute & send
            computeGravity();
        } else {
            System.out.println("is not");
            // send mail, not this
            computeGravity();
        }
    }
    
    public void computeGravity(){
      int humidity = Integer.parseInt(humidityPlante.getText().replaceFirst("^0+(?!$)", ""));
      int seuil = Integer.parseInt(humiditySeuil.getText().replaceFirst("^0+(?!$)", ""));
      System.out.println("humi " + humidity);
      System.out.println("seuil : " + seuil);
      if(humidity < (seuil / 2)) { // la moitié du seuil = critique, sound
          boolean tmp = true;
          while(tmp){
              try{
              this.workingThread.sendInstruction("SOUND");
              System.out.println("SOUND");
              tmp = false;              
              } catch(IOException e){
                  e.printStackTrace();
              }    
          }
          
      } else { // light
          boolean tmp = true;
          while(tmp){
              try{
              this.workingThread.sendInstruction("LIGHT");
              System.out.println("LIGHT");
              tmp = false;              
              } catch(IOException e){
                  e.printStackTrace();
              }    
          }
      }
    }
}