/*
 * 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 MailUtil.MailUtil;
import Util.CalendarUtil;
import java.io.IOException;
import java.net.URL;
import java.time.LocalDate;
import java.time.Period;
import java.util.Calendar;
import java.util.ResourceBundle;
import javafx.application.Platform;
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.ToggleGroup;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;


import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import javax.mail.*;
import javax.mail.internet.*;
import java.util.*;


/**
 * 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;
    LocalDate lastMailDay;

    
    /**
     * 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);
        
        //TODO initialize lastMailDay with database
        lastMailDay = LocalDate.of(2018, 12, 12);

        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 (humiditySeuil.getText() != null && Integer.parseInt(newValue) < Integer.parseInt(humiditySeuil.getText())) {
                    changeImagePlante(true);
                    alert = true;
                    if(Integer.parseInt(oldValue) >  Integer.parseInt(humiditySeuil.getText()) || Integer.parseInt(oldValue) == -1){ // start or change
                        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);
        
        initDB("plant.db");
    }    

    public static void initDB(String name) {
 
        String url = "jdbc:sqlite:C:/sqlite/" + name;
 
        try (Connection conn = DriverManager.getConnection(url)) {
            if (conn != null) {
                DatabaseMetaData meta = conn.getMetaData();
                createNewTable(url);
            }
 
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
    }
    
    
    /**
     * Create a new table in the test database
     *
     */
    public static void createNewTable(String url) {
        // SQLite connection string
        
        // SQL statement for creating a new table
        String sql = "CREATE TABLE IF NOT EXISTS data (\n"
                + "	id integer PRIMARY KEY AUTOINCREMENT,\n"
                + "     month integer NOT NULL CHECK(month <= 12 and month > 0),\n"
                + "     day integer NOT NULL CHECK(day <= 31 and day > 0),\n"
                + "     hour integer NOT NULL CHECK(hour <24 and hour >= 0),\n"
                + "     min integer NOT NULL CHECK(min <60 and min >= 0),\n"
                + "	intensity integer,\n"
                + "     temperature integer,\n"
                + "	humidityAir integer,\n"
                + "     humidityPlant integer\n"
                + ");";
        
        try (Connection conn = DriverManager.getConnection(url);
                Statement stmt = conn.createStatement()) {
            // create a new table
            stmt.execute(sql);
        } catch (SQLException e) {
            System.out.println("ewi" + e.getMessage());
        }
    }
    
     private Connection connect() {
        // SQLite connection string
        String url = "jdbc:sqlite:C://sqlite/plant.db";
        Connection conn = null;
        try {
            conn = DriverManager.getConnection(url);
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
        return conn;
    }
     
    public void insert(int month, int day, int hour, int min, int it, int temp, int humiA, int humiT) {
        String sql = "INSERT INTO data(month,day,hour,min,intensity,temperature,humidityAir,humidityPlant) VALUES(?,?,?,?,?,?,?,?)";
 
        try (Connection conn = this.connect();
                PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setInt(1, month);
            pstmt.setInt(2, day);
            pstmt.setInt(3, hour);
            pstmt.setInt(4, min);
            pstmt.setInt(5, it);
            pstmt.setInt(6, temp);
            pstmt.setInt(7, humiA);
            pstmt.setInt(8, humiT);
            pstmt.executeUpdate();
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
    }
    
    /**
     * 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(){
        computeGravity();
        if(CalendarUtil.isBusinessDay(Calendar.getInstance())){
            System.out.println("is business day");
        } else {
            System.out.println("is not business day");
            LocalDate today = LocalDate.now();
            Period difference = Period.between(lastMailDay, today);
            if(difference.getDays() > 1){
                // send mail
                MailUtil.sendDistressMail();
                lastMailDay = today;
            }
        }
    }
    
    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();
              }    
          }
      }
    }
}