package org.josast.ApplicationAmicalsat;

import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Logger;

import javax.imageio.ImageIO;

import org.josast.ApplicationAmicalsat.util.LogFile;
import org.josast.ModuleSoundModem.SoundModemConfiguration;
import org.josast.SIDS.Station;
import org.josast.amicalsat.Frame;
import org.josast.javafx.AlertHelper;
import org.josast.propertyHttp.ConfigHttp;

import javafx.application.Platform;
import javafx.concurrent.WorkerStateEvent;

import javafx.event.ActionEvent;
import javafx.event.EventHandler;

//import java.util.logging.Logger;

import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;
import javafx.stage.Window;
import javafx.embed.swing.SwingFXUtils;

public class Controler {
    
    private static final String LINE_SEPARATOR = "\r\n";
    private static final int STATE_INIT = 0;
    private static final int STATE_START = 1;
    protected static final int STATE_STOP = 2;
    private static final int STATE_SAVE = 3;
    
    private Logger appLogger = Logger.getLogger("AmicalSatLogger");
    private String version = "0.1";

    @FXML
    private Button ButtonStart;
    @FXML
    private Button ButtonStop;
    @FXML
    private Button ButtonSave;
    @FXML
    private Label LabelIP;

    @FXML
    private Button ButtonFile;
    @FXML
    private Button ButtonSerial;
    @FXML
    private Button ButtonKiss;

    @FXML
    private TextField FieldIP;
    @FXML
    private TextField FieldPort;

    @FXML
    private Label labelStatus;
    @FXML
    private Label LabelFrame;

    @FXML
    private TextArea DecodedData;

    @FXML
    private TextArea TexAreaLog;

    @FXML
    private TextField textFieldMode;

    @FXML
    private TextField textFieldDate;

    @FXML
    private Label LabelInformation;
    @FXML
    private TextField textFieldbEps33VCurrent;
    @FXML
    private TextField TextFieldEps5VCurrent;
    @FXML
    private TextField TextFieldepsBattVcurrent;
    @FXML
    private TextField TextFieldEpsTemp;
    @FXML
    private TextField TextFieldTrxTemp;
    @FXML
    private TextField TextFieldEPSVBAT;

    @FXML
    private TextField TFBattTemp;

    @FXML
    private ImageView ImageViewAMSAT;

    @FXML
    private ImageView imageViewEntrysat;

    @FXML
    private TextField TextFieldCallsign;
    @FXML
    private TextField TextFieldLatitude;
    @FXML
    private TextField TextFieldLongitude;

    @FXML
    private CheckBox CheckbBoxAmicalSat;
    @FXML
    private CheckBox CheckBoxSatNogs;

    @FXML
    private Button ButtonSaveConfiguration;

    @FXML
    TextField TextFieldSIDSEntrysat;
    @FXML
    TextField TextFieldSIDSSatnogs;

    Stage primaryStage = null;

    private String imgAmsat = "logoAmsat.png";
    private String imgAmicalsat = "Amicalsat.jpg";

    Station station = new Station();

    ModelReceivedData receivedFrame = new ModelReceivedData();
    Configuration conf = Configuration.getInstance();

    private TaskSoundmodemTCP task;
    private SendSIDS SendSIDSSatnogs;
    private SendSIDS SendSIDSEntrysat;
    private PrintWriter pw;
    private LogFile logfile=null;
    

    @FXML
    private void HandleSaveConfiguration(ActionEvent event) {
       
        String erreurmsg = null;
        String Callsign = null;
        
        
        if (TextFieldCallsign.getText().isEmpty()) {
            erreurmsg += "please enter a CallSign \r\n";
        } else {
            Callsign = TextFieldCallsign.getText();
        }

        String Latitude = TextFieldLatitude.getText();
        String Longitude = TextFieldLongitude.getText();

        if (station.checkLatitude(Latitude) == false) {
            erreurmsg += "Wrong format for Latitude : XX.XXE/W \r\n";
        }

        if (station.checkLongitude(Longitude) == false) {
            erreurmsg += "Wrong format for Longitude : XX.XXS/N \r\n";
        }
        if (erreurmsg != null) {
            Window owner = ButtonSaveConfiguration.getScene().getWindow();
            AlertHelper.showAlert(Alert.AlertType.ERROR, owner, "Form Error!", erreurmsg);
            return;
        }

        station.setCallsign(Callsign);
        station.setLatitude(Latitude);
        station.setLongitude(Longitude);

        conf.setCallsign(Callsign);
        conf.setLatitude(Latitude);
        conf.setLongitude(Longitude);

        conf.setSIDSEntrySatSource(TextFieldSIDSEntrysat.getText());
        conf.setSIDSSatnogsSource(TextFieldSIDSSatnogs.getText());
        conf.setSoundModemIP(FieldIP.getText());
        conf.setSoundModemPort(FieldPort.getText());

        Station StationSatnogs = new Station(conf.getSIDSSatnogsSource(), station.getLongitude(),
                station.getLatitude());
        Station StationEntry = new Station(conf.getSIDSEntrySatSource(), station.getLongitude(), station.getLatitude());

        if (CheckbBoxAmicalSat.isSelected() == true) {
            conf.setSIDSEntrySat("1");
            SendSIDSEntrysat = new SendSIDS(StationEntry, conf.getNorad(), conf.getSIDSEntryUrl());
        } else {
            conf.setSIDSEntrySat("0");

        }

        if (CheckBoxSatNogs.isSelected() == true) {
            conf.setSIDSSatnogs("1");
            SendSIDSSatnogs = new SendSIDS(StationSatnogs, conf.getNorad(), conf.getSIDSSatnogsURL());
        } else {
            conf.setSIDSSatnogs("0");
        }

        conf.save();
        manageStatusinformation("Configuration Saved","Configuration Saved");
        
    }

    @FXML
    private void handleStart(ActionEvent event) {


        manageStatusinformation("Connected to modem","Connection to modem");
        manageStateMMI(STATE_START);
         
        // TODO :  to improve
        SoundModemConfiguration smc = new SoundModemConfiguration("default");
        smc.setSmIPadress(FieldIP.getText());
        smc.setSmPort(Integer.parseInt(FieldPort.getText()));
        
        
        if (task == null) {
            receivedFrame.addPropertyChangeListener(new PropertyChangeListener() {
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    final Frame decodedData = receivedFrame.getLastDecodedData();
                    if (conf.isSIDS_EntrySat()) {
                        // Generation SIDS
                    }
                    Platform.runLater(new Runnable() {
                        @Override
                        public void run() {
                            try {
                        
                                if (decodedData != null) {
                                    displayLog(decodedData.toStringHeader());
                                    displayLog(decodedData.toString());    
                                    updateFrame(receivedFrame.getNumberFrame());

                                } else {
                                    displayLog("received frame  : null");
                                }

                            } catch (Exception e) {
                                displayLog("Run - error");
                                displayLog(e.toString());
                                e.printStackTrace();
                            }

                        }

                    });
                }

            }

            );

        }
        task = new TaskSoundmodemTCP(smc, receivedFrame);

        task.setOnSucceeded(new EventHandler<WorkerStateEvent>() {

            @Override
            public void handle(WorkerStateEvent event) {
                // La tache s'est correctement terminee.
                manageStatusinformation("KISS TCP CONNECTION FAILED","KISS TCP DISCONNECTED");
                manageStateMMI(STATE_STOP);

                }

        });

        task.setOnFailed(new EventHandler<WorkerStateEvent>() {

            @Override
            public void handle(WorkerStateEvent event) {
                // La tache s'est correctement terminee.
                manageStatusinformation("KISS TCP CONNECTION FAILED","KISS TCP DISCONNECTED - Connection failed");
                displayLog(event.toString());
                displayLog(event.getSource().toString());
                manageStateMMI(STATE_STOP);
            }

        });

        Thread backgroundThread = new Thread(task);
        backgroundThread.setDaemon(true);
        backgroundThread.start();

    }

    @FXML
    private void handleStop(ActionEvent event) {

        manageStateMMI(STATE_STOP);
        task.arreter();
        manageStatusinformation("Stop received data","Stop task to receive telemetrie");
    }

    @FXML
    private void handleSave(ActionEvent event) {

        
        manageStateMMI(STATE_SAVE);
        manageStatusinformation("save data","save Telemetry in file");
        saveDataFile();
        manageStatusinformation("Data Saved","Telemetry Data saved in file");
    }



    @FXML
    private void HandleIP(ActionEvent event) {
    }

    @FXML
    private void HandlePort(ActionEvent event) {
    }



    public void initMMI() {

        
        logfile = new LogFile();
        // initialise le log
 //       initdisplayLogFile();

        manageStatusinformation("Initialised","ENTRY SAT - LOG \r\n Initialise application") ;   
        appLogger.warning("Initialise ");
        primaryStage.setTitle("AmicalSat Decoder - " + version);

        station.setCallsign(conf.getCallsign());
        station.setLatitude(conf.getLatitude());
        station.setLongitude(conf.getLongitude());

        TextFieldCallsign.setText(station.getCallsign());
        TextFieldLatitude.setText(station.getLatitude());
        TextFieldLongitude.setText(station.getLongitude());

        TextFieldSIDSEntrysat.setText(conf.getSIDSEntrySatSource());
        TextFieldSIDSSatnogs.setText(conf.getSIDSSatnogsSource());

         
        if (conf.isSIDS_EntrySat()) {
            CheckbBoxAmicalSat.setSelected(true);
        }
        if (conf.isSISD_SatNogs()) {
            CheckBoxSatNogs.setSelected(true);
        }

        displayLog(conf.getSIDSSatnogsURL());
        displayLog(conf.getSIDSEntryUrl());
        displayLog("Initialisation with Properties File Done ");

        BufferedImage bufferedImage1 = null;
        BufferedImage bufferedImage2 = null;

        try {
            
 
            bufferedImage1 = ImageIO.read(getClass().getResource((imgAmsat)));
               bufferedImage2 = ImageIO.read(getClass().getResource((imgAmicalsat)));
        } catch (IOException e) {

            appLogger.severe("Error loading Image resources");
            appLogger.severe(e.toString());
        }
        Image imageamsat = SwingFXUtils.toFXImage(bufferedImage1, null);
        ImageViewAMSAT.setImage(imageamsat);
        Image imgQB = SwingFXUtils.toFXImage(bufferedImage2, null);
           imageViewEntrysat.setImage(imgQB);

 
        ConfigHttp c = new ConfigHttp("http://site.amsat-f.org/download/117168/");
        String ver;
        String message;
        int NoradIdConf=conf.getNorad();
        if(c.isConnected())
        {
        ver = c.GetProperty("AmicalsatVersion");
        message = c.GetProperty("Message");
        NoradIdConf= Integer.parseUnsignedInt(c.GetProperty("NoradID").trim());
        }
        else
        {
            ver = version;
            message = "not connected to internet";
        }
        if (NoradIdConf!=conf.getNorad())
        {
            conf.setNorad(NoradIdConf);
            conf.save();
            displayLog("Norad ID updated  ");
        }
        
        manageStateMMI(STATE_INIT);
        manageStatusinformation("Application Ready","Application initialised") ;   
        this.LabelInformation.setText("");

        // initialise SIDS

        Station StationSatnogs = new Station(conf.getSIDSSatnogsSource(), station.getLongitude(),
                station.getLatitude());
        Station StationEntry = new Station(conf.getSIDSEntrySatSource(), station.getLongitude(), station.getLatitude());

        if (conf.isSISD_SatNogs() == true) {
            SendSIDSSatnogs = new SendSIDS(StationSatnogs, conf.getNorad(), conf.getSIDSSatnogsURL());
        }

        if (conf.isSIDS_EntrySat() == true) {
            SendSIDSEntrysat = new SendSIDS(StationEntry, conf.getNorad(), conf.getSIDSEntryUrl());
        }

        String erreurmsg = message;

        if (ver.equals(version) == false) {
            erreurmsg += " New version " + ver + " available ! ";

        }
        this.LabelInformation.setText(erreurmsg);

    }

    public void setPrimaryStage(Stage primaryStage) {
        this.primaryStage = primaryStage;

    }
    
    
    /**
     * Save telemetry data received in text file. The file is stored in data folder.
     */
    public void saveDataFile() {
        SimpleDateFormat formater = new SimpleDateFormat("yyyy-MM-dd-HHmmss");
        Date aujourdhui = new Date();

        // 

        String path = System.getProperty("user.dir") + "/data";
        File apath = new File(path);

        if (!apath.exists()) {
            if (apath.mkdir() == false) {
                appLogger.severe("fail to create " + path);
            }
        }

        PrintWriter pw = null;

        long NbFrame = receivedFrame.getNumberFrame();

        try {
            pw = new PrintWriter(new FileWriter(path + "/" + formater.format(aujourdhui) + "-tlm-Hexa.txt"));
            for (int i = 0; i < NbFrame; i++) {
  //              pw.write(receivedFrame.getFrame(i));
                pw.write(LINE_SEPARATOR);
            }

            pw.flush();
            pw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private void updateFrame(long nbframe) {
        LabelFrame.setText("frame : " + nbframe);

    }

    
    private void displayLog(String log) {

        logfile.displayLog(log);
        TexAreaLog.appendText(log);
        TexAreaLog.appendText("\r\n");
    }


    
    private void manageStateMMI(int state)
    {
        switch (state) {
            case STATE_INIT : 
                ButtonStop.setDisable(true);
                ButtonStart.setDisable(false);
                ButtonSave.setDisable(true);
                break;
            case STATE_START : 
                ButtonStop.setDisable(false);
                ButtonStart.setDisable(true);
                ButtonSave.setDisable(false);
                break;
            case STATE_STOP : 
                ButtonStop.setDisable(true);
                ButtonStart.setDisable(false);
                ButtonSave.setDisable(false);
                break;
            case  STATE_SAVE :
                ButtonStop.setDisable(true);
                ButtonStart.setDisable(false);
                ButtonSave.setDisable(true);
                break;
            
            
        }
    }
    
    private void manageStatusinformation(String statusMessage, String logMessage) {
        labelStatus.setText(statusMessage);
        displayLog(logMessage);
        
    }

}
