package ch.hevs.isi;

import ch.hevs.isi.core.BooleanDataPoint;
import ch.hevs.isi.core.DataPoint;
import ch.hevs.isi.core.FloatDataPoint;
import ch.hevs.isi.db.DatabaseConnector;
import ch.hevs.isi.field.FieldConnector;
import ch.hevs.isi.utils.Utility;
import ch.hevs.isi.web.WebConnector;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;

public class MinecraftController {

    public static boolean ERASE_PREVIOUS_DATA_INB_DB        = false;
    private static final Properties properties = new Properties(); // Properties of the config.properties file

    public static void usage() {
        System.out.println();
        System.out.println("You're reading this message because no parameter (or not the needed ones) has been passed to the application.");
        System.out.println();
        System.out.println("In development mode, just add to your running configuration the needed parameters (see usage below).");
        System.out.println("In running mode, the application's usage is the following:");
        System.out.println("java MinecraftController <db_url> <db_org> <db_bucket> <db_token> <modbus_host> <modbus_port> [-erasedb]");
        System.out.println("where:");
        System.out.println("- <db_url>:           The complete URL of the InfluxDB server, including the protocol (http or https)...");
        System.out.println("                      Example: https://influx.sdi.hevs.ch");
        System.out.println("- <db_org>:           The name of the Influx DB to use. For this project, this name is the name of the group you've been affected to. (SInXX)");
        System.out.println("- <db_bucket>:        The user's name to use to access the DB. It's also your group's name. (SInXX)");
        System.out.println("- <db_token>:         The Token to use to access the DB.");
        System.out.println("- <modbus_host>:      The IP address of the Minecraft ModbusTCP server (default value: localhost)");
        System.out.println("- <modbus_port>:      The port number of the Minecraft ModbusTCP server (default value: 1502)");
        System.out.println("- [-eraseDB]:         Optional parameter! If set, the application will erase the previous data in InfluxDB...");
        System.out.println();
        System.exit(1);
    }

    @SuppressWarnings("all")
    public static void main(String[] args) throws InterruptedException {

        // ------------------------------------- DO NOT CHANGE THE FOLLOWING LINES -------------------------------------
        String dbProtocol       = "http";
        String dbHostName       = "localhost";
        String dbName           = "labo";
        String dbUserName       = "root";
        String dbPassword       = "root";
        String dbToken          = "super-token";

        String modbusTcpHost    = "localhost";
        int modbusTcpPort       = 1502;

        // Check the number of arguments and show usage message if the number does not match.
        String[] parameters = null;

        // If there is only one number given as parameter, construct the parameters according the group number.
        if (args.length >= 6) {
            parameters = args;

            // Decode parameters for influxDB
            String[] dbParams = parameters[0].split("://");
            if (dbParams.length != 2) {
                usage();
            }

            dbProtocol    = dbParams[0];
            dbHostName    = dbParams[1];
            dbName        = parameters[1];
            dbUserName    = parameters[2];
            dbPassword    = Utility.md5sum(dbUserName);
            dbToken       = parameters[3];

            // Decode parameters for Modbus TCP
            modbusTcpHost = parameters[4];
            modbusTcpPort = Integer.parseInt(parameters[5]);

            for (int i = 5; i < args.length; i++) {
                if (parameters[i].compareToIgnoreCase("-erasedb") == 0) {
                    ERASE_PREVIOUS_DATA_INB_DB = true;
                }
            }
        } else {
            usage();
        }

        // ------------------------------------ /DO NOT CHANGE THE FOLLOWING LINES -------------------------------------

        // Read the config.properties file
        /*
        try (InputStream input = new FileInputStream("config.properties")) {
            properties.load(input);
        } catch (Exception e) {
            e.printStackTrace();
        }
        */

        // Initialize the database connector
        if(dbName != null){
            DatabaseConnector.org = dbName;
        }
        if(dbUserName != null){
            DatabaseConnector.bucket = dbUserName;
        }

        DatabaseConnector.token = dbToken;
        if((dbProtocol != null) && (dbHostName != null)){
            DatabaseConnector.url = dbProtocol+ "://" + dbHostName;
            DatabaseConnector.getMySelf().initialize(DatabaseConnector.url);
            System.out.println("Database is running on " + DatabaseConnector.url);
        }

        // Initialize the Modbus TCP connector
        FieldConnector.getMySelf().initialize(modbusTcpHost, modbusTcpPort,"ModbusMap.csv");
        System.out.println("Field is running on " + modbusTcpHost + ":" + modbusTcpPort);

        // Initialize the web server
        /*
        String host = properties.getProperty("WEB.URL");
        int port = Integer.parseInt(properties.getProperty("WEB.PORT"));
        */
        String host = "localhost";
        int port = 8888;
        WebConnector.getMySelf().initialize(host, port);
        System.out.println("Web server is running on " + host + ":" + port);


        SmartControl smartControl = new SmartControl();
        System.out.println("SmartControl is running");
        while (true) {
            BooleanDataPoint man = (BooleanDataPoint) DataPoint.getDataPointOnListFromLabel("REMOTE_MAN_SW");
            boolean autoMode = true;
            if(man != null) autoMode = !man.getValue();

            if (autoMode){
                boolean stateGrid = true;
                try {
                    stateGrid = smartControl.run();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if(!stateGrid) System.out.println("Grid is not fine");
            }

            FloatDataPoint score = (FloatDataPoint) DataPoint.getDataPointOnListFromLabel("SCORE");
            if(score != null) {
                if(score.getValue() >= 100) {
                    System.out.println("Game finished with score: " + score.getValue());
                    System.exit(0);
                }
            }

            Thread.sleep(SmartControl.TIME_BETWEEN_UPDATES);
        }


    }
}
