package cz.feec.vutbr.WebApp;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Date;

@Lazy(false)
@Component
@EnableScheduling
public class SpringDynamicCronTask implements SchedulingConfigurer {

    private static final String DEFAULT_CRON = "0 10 0 * * 1";
    public String cron = DEFAULT_CRON;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(() -> {
            System.out.println("\n"+new Date()+" Scheduled Cron job: Epoch change");
            try {
                InetAddress inet = InetAddress.getByName(StudentController.raAddress);
                if (inet.isReachable(2000)){
                    //online epoch change, pokračování dole
                }
                else{
                    //offline epoch change
                    System.out.println(new Date()+" RA IP address is not reachable. Changing epoch offline.");
                    RKVAC_handler offChangeEpoch = new RKVAC_handler();
                    offChangeEpoch.addAttributes("-v");
                    offChangeEpoch.addAttributes("-e");
                    String ep = null;
                    try {
                        String result = offChangeEpoch.start();
                        String epoch = new String(Files.readAllBytes(Path.of("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ve_epoch.dat")));
                        ep = epoch;
                        if (result.contains("Switch to the new epoch successful")){
                            System.out.println(new Date() +" New epoch: " + epoch);
                        }
                    }catch (InterruptedException e) {
                        e.printStackTrace();
                    }catch (IOException e) {
                        e.printStackTrace();
                    }
                }//konec offline change
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }//konec validace IP

            //online epoch change
            try{
            System.out.println("\n"+new Date() + " Online Epoch Change Initialized. RA IP Address: " +StudentController.raAddress +" 5004");
            RKVAC_handler change = new RKVAC_handler();
            change.addAttributes("-v");
            change.addAttributes("-e");
            String container = change.start();

            //move /data/Verifier/ve_epoch_for_RA.dat to RA, New Socket
            Socket clientRA = new Socket(StudentController.raAddress, 5004);
            String epoch = new String(Files.readAllBytes(Path.of("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ve_epoch.dat")));

            DataOutputStream dos = new DataOutputStream(clientRA.getOutputStream());
            FileInputStream fis = new FileInputStream(new File("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ve_epoch_for_RA.dat"));
            byte[] buffer = new byte[4096];
            System.out.println(new Date() + " --> Sending ve_epoch_for_RA.dat");
            dos.write(epoch.getBytes());

            // Read data from the server until we finish reading the document
            //./data/RA/ra_BL_epoch_02270421_C_for_verifier.dat ./data/Verifier/ra_BL_epoch_02270421_C_for_verifier.dat
            DataInputStream dis = new DataInputStream(clientRA.getInputStream());
            FileOutputStream fos = new FileOutputStream(new File("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ra_BL_epoch_"+epoch+"_C_for_verifier.dat"));
            System.out.println(new Date()+" <-- Reading for /home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ra_BL_epoch_"+epoch+"_C_for_verifier.dat");
            int count = 0;
            byte[] buffer2 = new byte[4096];
            while ((count = dis.read(buffer2)) > 0)
            {
                fos.write(buffer2, 0, count);
            }

            //rewrite blacklist -v -w ./data/Verifier/ra_BL_epoch_02270421_C_for_verifier.dat
            System.out.println(new Date() +" Rewriting blacklist");
            RKVAC_handler rewrite = new RKVAC_handler();
            rewrite.addAttributes("-v");
            rewrite.addAttributes("-w");
            String raBlepoch = "/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ra_BL_epoch_"+epoch+"_C_for_verifier.dat";
            rewrite.addAttributes(raBlepoch);
            String rewriting = rewrite.start();
            System.out.println(new Date() +" New epoch: " + epoch);
        }catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        }, triggerContext -> {
            CronTrigger trigger = new CronTrigger(cron);
            return trigger.nextExecutionTime(triggerContext);
        });
    }
    public void setCron(String cron) {
        System.out.println("The original cron: "+this.cron+" The updated cron: "+cron);
        this.cron = cron;
    }
    public String getCron() {
        return this.cron;
    }
}
