package cz.feec.vutbr.WebApp;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.support.CronSequenceGenerator;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.validation.Valid;
import java.io.*;
import java.net.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


@Controller
@RequestMapping("/admin/")
public class StudentController {
    private final StudentRepository studentRepository;
    public static String raAddress;
    public static String epoch;
    private static int settingsWarning = 0;


    @Autowired
    public StudentController(StudentRepository studentRepository) {
        this.studentRepository = studentRepository;
    }

    @Autowired
    public SpringDynamicCronTask springDynamicCronTask;

    @GetMapping("index")
    public String showAttributeIndex(Model model) {
        model.addAttribute("students", studentRepository.findAll());
        return "crud";
    }
    @GetMapping("parameters")
    public String getParameters(Model model){
        File ie_sk = new File("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ie_sk.dat");
        File ra_pk = new File("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ra_pk.dat");
        File ra_public_parameters = new File("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ra_public_parameters.dat");

        if (ie_sk.exists()){
            model.addAttribute("ie_sk", "Found");
        }
        else{
            model.addAttribute("ie_sk", "Not found");
        }
        if (ra_pk.exists()){
            model.addAttribute("ra_pk","Found");
        }
        else {
            model.addAttribute("ra_pk","Not found");
        }
        if (ra_public_parameters.exists()){
            model.addAttribute("ra_pub","Found");
        }
        else{
            model.addAttribute("ra_pub","Not found");
        }
       return "parameters";
    }
    @GetMapping("logs")
    public String getLogs(Model model){
        ArrayList lines;
        try {
            lines = Read_file.read("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ve_requests.log");
            ArrayList<VerifierRequests> reqList = new ArrayList<VerifierRequests>();
            for (var line: lines) {
                try {
                String[] words = line.toString().split("\\s+");
                //System.out.println(Arrays.toString(words));
                VerifierRequests verreq = new VerifierRequests();
                verreq.setDate(words[0] + " "+ words[1] + " "+ words[2] + " "+ words[3]+ " "+ words[4]);
                verreq.setEpoch(words[5]);
                verreq.setPseudonym(words[6]);
                verreq.setStatus(words[7] +" " +words[8]);

                reqList.add(verreq);
                }catch (IndexOutOfBoundsException e){
                    System.out.println(new Date()+" Error while reading ve_requests.log line, skipping badly formated line! Please check file data/Verifier/ve_requests.log.");
                }
            }

            //cut size to #50 elements
/*            if (reqList.size() > 50){
                int size = (reqList.size() - 50);
                for (int i = 0; i < size; i++) {
                    reqList.remove(reqList.indexOf(i));

                }
            }*/
            if (reqList.size() > 50){
                List last50 = reqList.subList(reqList.size()-50, reqList.size());
                model.addAttribute("list",last50);
            }else{
                model.addAttribute("list",reqList);
            }
        } catch (IOException e) {
            System.out.println(new Date()+" Can´t read ..Verifier/ve_requests.log");
            e.printStackTrace();
        }

        return "logs";
    }
    @GetMapping("settings")
    public String getSettings(Model model){

        //Warning box
        if (settingsWarning == 1) {
            CronSequenceGenerator generator = new CronSequenceGenerator(springDynamicCronTask.getCron());
            Date nextRunDate= generator.next(new Date());
            String attributeValue= "<div class=\"alert alert-warning\" role=\"alert\" style=\"text-align:center;\">\n" +
                    "Scheduled epoch switch changed! Next run scheduled to: <b>"+nextRunDate.toString()+"</b> <br><b>Please restart the service to apply changes.</b> \n" +
                    "</div>";
            model.addAttribute("warning", attributeValue);
        }
        //RA Address Card
        try {
            InetAddress inet = InetAddress.getByName(raAddress);

                 if (inet.isReachable(2000)){
                     model.addAttribute("raAddress",raAddress);
                     model.addAttribute("raStatus","Reachable");
                 }
                 else{
                     model.addAttribute("raAddress",raAddress);
                     model.addAttribute("raStatus","Not reachable");
                 }

        } catch (UnknownHostException e) {
            model.addAttribute("raAddress",raAddress);
            model.addAttribute("raStatus", "Invalid IPv4 address");
        } catch (IOException e) {
            model.addAttribute("raAddress",raAddress);
            model.addAttribute("raStatus", "Invalid IPv4 address");
        }

        //Current Epoch
        try {
            String epoch = new String(Files.readAllBytes(Path.of("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ve_epoch.dat")));
            model.addAttribute("epoch",epoch);
        } catch (IOException e) {
            e.printStackTrace();
            model.addAttribute("epoch","Not found");
        }

        //Verification Loop
        if (WebController.inCycles){
            model.addAttribute("inCycles","ENABLED");
        }else {
            model.addAttribute("inCycles","DISABLED");
        }

        //Epoch change interval table
        model.addAttribute("cronValue",springDynamicCronTask.getCron().substring(1));
        CronSequenceGenerator generator = new CronSequenceGenerator(springDynamicCronTask.getCron());
        Date nextRunDate= generator.next(new Date());
        model.addAttribute("cronDate", nextRunDate.toString());

        return "settings";
    }

    @GetMapping("signup")
    public String showSignUpForm(Student student) {
        return "add-student";
    }

    @GetMapping("list")
    public String showUpdateForm(Model model) {
        model.addAttribute("students", studentRepository.findAll());

        return "crud";
    }

    @PostMapping("add")
    public String addStudent(@Valid Student student, BindingResult result, Model model) {
        if (result.hasErrors()) {
            return "add-student";
        }

/*        //ověř, že student a pověření neexistují, pokud ano, vymaž je z databáze i z disku a ulož nového
        String name = student.getName().replace(" ", "").toLowerCase();
        File f = new File("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/"+name);
        if(f.exists() && !f.isDirectory()) {
            f.delete();
            for (Student st: studentRepository.findAll()) {
                if (st.getName().replace(" ", "").toLowerCase() == name){
                    studentRepository.deleteById(st.getId());
                }
            }
        }
        issueCredentials(student, model);*/


        studentRepository.save(student);
        saveDatabase();
        return "redirect:list";
    }

    @GetMapping("edit/{id}")
    public String showUpdateForm(@PathVariable("id") long id, Model model) {
        Student student = studentRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("Invalid credential Id:" + id));
        model.addAttribute("student", student);
        return "update-student";
    }

    @GetMapping("active/{id}")
    public String setActiveAttribute(@PathVariable("id") long id, Model model) {
        Student active = studentRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("Invalid credential Id:" + id));
/*
        //cache
        String prevName = student.getName();
        student.setName("active");
        //odstranění původního active pověření
        File f = new File("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/"+"active");
        if(f.exists() && !f.isDirectory()) {
            f.delete();
        }
        issueCredentials(student, model);
        //nastav všechny v databázi na false
        for (Student st: studentRepository.findAll()) {
            st.setActive(false);
            studentRepository.save(st);
        }
        //nastav konkrétního na active
        student.setActive(true);
        student.setName(prevName);
        studentRepository.save(student);
*/
        for (Student cred: studentRepository.findAll()) {
            cred.setStatus("-");
            studentRepository.save(cred);
        }
        active.setStatus("ACTIVE");
        WebController.active = active;
        studentRepository.save(active);
        saveDatabase();
/*        try {
            File file = new File("/home/rkvac/rkvac_web/active.dat");

            if(file.exists() && !file.isDirectory()) {
                file.delete();
            }
            FileOutputStream f = new FileOutputStream(file);
            ObjectOutputStream o = new ObjectOutputStream(f);
            o.writeObject(active);




            o.close();
            f.close();

        } catch (FileNotFoundException e) {
            System.out.println("File not found");
        } catch (IOException e) {
            System.out.println("Error initializing stream");
        }*/
        System.out.println(new Date()+" Deploying credentials " + active.getName() + " successful." );

        model.addAttribute("students", studentRepository.findAll());
        return "crud";
    }

    @PostMapping("update/{id}")
    public String updateStudent(@PathVariable("id") long id, @Valid Student student, BindingResult result,
                                Model model) {
        if (result.hasErrors()) {
            student.setId(id);
            return "update-student";
        }

        studentRepository.save(student);

       /* String name = student.getName().replace(" ", "").toLowerCase();
        System.out.println("-------------------------------------------------------------");
        System.out.println("Updating Credentials ..Verifier/" + name);
        System.out.println("-------------------------------------------------------------");
        File myObj = new File("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/"+name);
        myObj.delete();
        issueCredentials(student, model);*/

        saveDatabase();
        model.addAttribute("students", studentRepository.findAll());
        return "crud";
    }

    @GetMapping("delete/{id}")
    public String deleteStudent(@PathVariable("id") long id, Model model) {
        Student student = studentRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("Invalid student Id:" + id));
        studentRepository.delete(student);

        /*String name = student.getName().replace(" ", "").toLowerCase();
        System.out.println("-------------------------------------------------------------");
        System.out.println("Deleting Credentials ..Verifier/" + name);
        File myObj = new File("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/"+name);
        myObj.delete();
        System.out.println("-------------------------------------------------------------");*/
        saveDatabase();
        model.addAttribute("students", studentRepository.findAll());
        return "crud";
    }

/*    @GetMapping
    public String issueCredentials(Student student, Model model){
        RKVAC_handler rkvac = new RKVAC_handler();

        rkvac.addAttributes("-v");
        rkvac.addAttributes("-a");
        String name = student.getName().replace(" ", "").toLowerCase();
        rkvac.addAttributes(name);

        rkvac.addUser_input("4");
        rkvac.addUser_input(String.valueOf(student.getAttributeCount()));

        if (student.getAtt1() != ""){rkvac.addUser_input(student.getAtt1());}
        if (student.getAtt2() != ""){rkvac.addUser_input(student.getAtt2());}
        if (student.getAtt3() != ""){rkvac.addUser_input(student.getAtt3());}
        if (student.getAtt4() != ""){rkvac.addUser_input(student.getAtt4());}
        if (student.getAtt5() != ""){rkvac.addUser_input(student.getAtt5());}
        if (student.getAtt6() != ""){rkvac.addUser_input(student.getAtt6());}
        if (student.getAtt7() != ""){rkvac.addUser_input(student.getAtt7());}
        if (student.getAtt8() != ""){rkvac.addUser_input(student.getAtt8());}
        if (student.getAtt9() != ""){rkvac.addUser_input(student.getAtt9());}
        rkvac.addUser_input(student.getActivePositions());

        try {
            String container = rkvac.start();


            if (!container.contains("Issuer part complete")){
                new Exception(container);
                model.addAttribute("container", container);
                return "fail";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "ok";

    }
*/
    @GetMapping("save")
    public String saveDatabase(){
        try {
            File file = new File("/home/rkvac/rkvac_web/credentials.dat");

            if(file.exists() && !file.isDirectory()) {
                file.delete();
            }
            FileOutputStream f = new FileOutputStream(file);
            ObjectOutputStream o = new ObjectOutputStream(f);

            // Write objects to file
            ArrayList<Student> list = new ArrayList<Student>();
            for (Student credential: studentRepository.findAll()
                 ) {
                list.add(credential);
                if (credential.getStatus().equals("ACTIVE")){
                    WebController.active = credential;

                }
            }
            o.writeObject(list);


            System.out.println("\n"+new Date()+" Saving database /home/rkvac/rkvac_web/credentials.dat successful." );

            o.close();
            f.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.out.println(new Date()+" File not found");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println(new Date()+" Error initializing stream");
        }
    return "redirect:list";
    }
    @PostConstruct
    @GetMapping("load")
    public String loadDatabase(){
        studentRepository.deleteAll();
        System.out.println(new Date()+" Checking for a credential database...");
        try {
            FileInputStream fi = new FileInputStream(new File("/home/rkvac/rkvac_web/credentials.dat"));
            ObjectInputStream oi = new ObjectInputStream(fi);

            // Read objects
            ArrayList<Student> list = (ArrayList<Student>) oi.readObject();
            for (Student cred: list) {
                studentRepository.save(cred);
                if (cred.getStatus().equals("ACTIVE")){
                    WebController.active = cred;

                }
            }

            System.out.println(new Date()+" Loading database /home/rkvac/rkvac_web/credentials.dat successful." );
            oi.close();
            fi.close();



        } catch (FileNotFoundException e) {
            System.out.println(new Date()+" No database found... File /home/rkvac/rkvac_web/credentials.dat does´t exist");
        } catch (IOException e) {
            System.out.println(new Date()+" Error initializing stream, possible corrupted file database.dat");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            //Defaultní nastavení databáze
            if (WebController.active == null){
                System.out.println(new Date()+" No active credential record found, deploying defaults. Please check Administration.");
                Student def = new Student();
                def.setId(99999);
                def.setName("default");
                def.setStatus("ACTIVE");
                def.setAtt2("BUT");
                def.setActivePositions("2");
                def.setAttributeCount(5);
                studentRepository.save(def);
                WebController.active = def;
            }
        }

        try {
            System.out.print(new Date()+" Loading settings...");
            FileInputStream fi = new FileInputStream(new File("/home/rkvac/rkvac_web/settings.dat"));
            ObjectInputStream oi = new ObjectInputStream(fi);
            Settings settings = (Settings) oi.readObject();
            WebController.inCycles = settings.getInCycles();
            StudentController.raAddress = settings.getRAaddress();
            springDynamicCronTask.cron = settings.getCron();
            WebController.cr= springDynamicCronTask.getCron();
            System.out.println(" Epoch: " + new String(Files.readAllBytes(Path.of("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ve_epoch.dat")))+ ", RA IP: "+ raAddress+", Cron scheduled epoch change: "+ springDynamicCronTask.getCron().substring(1));
        } catch (FileNotFoundException e) {
            System.out.println("\n"+new Date()+" No settings file found, please check Administration.");

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        return "redirect:list";

    }

    @PostMapping("settings/set-ra-address")
    public String setRaAddress(@RequestParam String raIP, Model model) {
        Settings settings = new Settings();



        InetAddress inet = null;


        try {
            //IP check
            inet = InetAddress.getByName(raIP);
            if (raIP.equals("") || raIP.equals(null)){
                model.addAttribute("message", "Empty IPv4 address. Please set a valid address." );
                return "settings-err";
            }
            else{
                if (inet.isReachable(2000)){
                    System.out.println(new Date()+ " Setting RA IPv4 address: " + raIP);
                    System.out.println(new Date()+ " "+raIP +":"+" ONLINE");
                }
                else{
                    System.out.println(new Date()+ " Setting RA IPv4 address: " + raIP);
                    System.out.println(new Date()+ " "+raIP +":"+" not reachable");
                }

            }

            raAddress = raIP;

            FileOutputStream f = new FileOutputStream(new File("/home/rkvac/rkvac_web/settings.dat"));
            ObjectOutputStream o = new ObjectOutputStream(f);


            settings.setRAaddress(raIP);
            settings.setInCycles(WebController.inCycles);
            settings.setCron(springDynamicCronTask.getCron());

            o.writeObject(settings);
            f.close();
            o.close();
        } catch (UnknownHostException e) {
            System.out.println(new Date()+ " Setting RA IPv4 address: " + raIP);
            System.out.println(new Date()+ " "+raIP +":"+" invalid IPv4 address.");
            model.addAttribute("message", "Invalid Revocation Authority IPv4 address: "+ raIP+"<br>Please set a valid address." );
            return "settings-err";
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            model.addAttribute("message", "Failed to set RA IPv4 Address. Please check system logs." );
            return "settings-err";
        } catch (IOException e) {
            e.printStackTrace();
            model.addAttribute("message", "Failed to set RA IPv4 Address. Please check system logs." );
            return "settings-err";
        }
        model.addAttribute("message", "Revocation Authority IPv4 address successfully changed. <br>New address: "+raIP);
        return "settings-ok";
        //return "redirect:/admin/settings";
    }

    @PostMapping("settings/set-cron-epoch")
    public String setCronEpoch(@RequestParam String cron, Model model) {
        cron = "0 "+cron;
        if (CronSequenceGenerator.isValidExpression(cron)){

        }else {
            model.addAttribute("message", "Can´t setup cron scheduler for epoch change. <br>Invalid cron expression. ");
            return "settings-err";
        }
        System.out.println(new Date()+" Changing cron job for epoch change to: "+cron.substring(1));
        springDynamicCronTask.setCron(cron);
        Settings settings = new Settings();
        settings.setInCycles(WebController.inCycles);
        settings.setRAaddress(raAddress);
        settings.setCron(cron);

        try {
            FileOutputStream f = new FileOutputStream(new File("/home/rkvac/rkvac_web/settings.dat"));
            ObjectOutputStream o = null;
            o = new ObjectOutputStream(f);
            o.writeObject(settings);
            f.close();
            o.close();
        } catch (IOException e) {
            e.printStackTrace();
            model.addAttribute("message", "Failed to save cronjob to settings. Please check system logs." );
            return "settings-err";
        }

        CronSequenceGenerator generator = new CronSequenceGenerator(cron);
        Date nextRunDate= generator.next(new Date());
        System.out.println(new Date()+" Next epoch change scheduled to: "+nextRunDate+". Please restart the application to load changes.");
        settingsWarning = 1;
        model.addAttribute("message", "Cron job changed to: "+cron.substring(1)+" <br>Next run scheduled to: "+nextRunDate+ " <br>Please restart the service to load changes.");
        return "settings-ok";
    }


    @GetMapping("settings/epoch-change")
    public String changeEpoch(Model model)  {


        String ep = null;
        try {
            //IP check
            if (isValidInet4Address(raAddress)){
                InetAddress inet = InetAddress.getByName(raAddress);
                if (inet.isReachable(2000) && (raAddress != " " || raAddress != "")){

                }
                else{
                    System.out.println("\n"+new Date()+" Online Epoch Change - RA IPv4 Address not reachable");
                    model.addAttribute("message", "Failed to change epoch. Revocation Authority IPv4 address is not reachable. Please check internet connection." );
                    return "settings-err";
                }
            }else {
                System.out.println("\n"+new Date()+" Online Epoch Change - Invalid RA IPv4 Address");
                model.addAttribute("message", "Failed to change epoch. Invalid Revocation Authority IPv4 address: "+ raAddress+"<br>Please set a valid address in settings." );
                return "settings-err";
            }

            System.out.println("\n"+new Date() + " Online Epoch Change Initialized. RA IP Address: " +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(raAddress, 5004);
            String epoch = new String(Files.readAllBytes(Path.of("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ve_epoch.dat")));
            ep = epoch;

            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());
    /*    while (fis.read(buffer) > 0) {
            dos.write(buffer);

        }*/

            // Read data from the server until we finish reading the document
            //listen mv ./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);
            }
/*        while ((count = dis.read(buffer)) != -1) {
            fos.write(buffer, 0, count);
        }*/
            // closing socket & stream




            //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();
            model.addAttribute("message", "Failed to change epoch. Please check system logs." );
            return "settings-err";
        } catch (InterruptedException e) {
            e.printStackTrace();
            model.addAttribute("message", "Failed to change epoch. Please check system logs." );
            return "settings-err";
        }


        model.addAttribute("message", "Epoch successfully changed with synchronization with Revocation Authority. <br>Blacklist successfully rewritten. <br>New Epoch: " + ep);
        return "settings-ok";
    }

    @GetMapping("settings/offline-epoch-change")
    public static String offlineEpochChange(Model model){
        System.out.println("\n"+new Date()+" Offline Epoch Change Initialized");
        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();
            model.addAttribute("message", "Epoch not changed. Please check system logs." );
            return "settings-err";
        }catch (IOException e) {
            e.printStackTrace();
            model.addAttribute("message", "Epoch not changed. Please check system logs." );
            return "settings-err";
        }

        model.addAttribute("message", "Epoch successfully changed. <br>New Epoch: " + ep);
        return "settings-ok";
    }

    @GetMapping("settings/disableverification")
    public String disableVerification(Model model)  {
        Settings settings = new Settings();
        settings.setInCycles(false);
        settings.setRAaddress(raAddress);
        settings.setCron(springDynamicCronTask.getCron());
        System.out.println(new Date()+" Disabling verification...");
        FileOutputStream f = null;
        try {
            f = new FileOutputStream(new File("/home/rkvac/rkvac_web/settings.dat"));
            ObjectOutputStream o = new ObjectOutputStream(f);

            o.writeObject(settings);
            f.close();
            o.close();
            WebController.inCycles = false;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            model.addAttribute("message", "Failed to disable verification. Please check system logs." );
            return "settings-err";
        } catch (IOException e) {
            e.printStackTrace();
            model.addAttribute("message", "Failed to disable verification. Please check system logs." );
            return "settings-err";
        }

        try {
            Process process = Runtime.getRuntime().exec("pkill -9 rkvac-protocol");
        } catch (IOException e) {
            model.addAttribute("message", "Verification successfully disabled. <br>Can´t reload rkvac service. Please restart the service");
            return "settings-err";
        }

        model.addAttribute("message", "Verification successfully disabled.");
        return "settings-ok";
        //return "redirect:/admin/settings";
    }

    @GetMapping("settings/enableverification")
    public String enableVerification(Model model)  {
        Settings settings = new Settings();
        settings.setInCycles(true);
        settings.setRAaddress(raAddress);
        settings.setCron(springDynamicCronTask.getCron());


        try {
            System.out.println(new Date()+" Enabling verification...");
            FileOutputStream f = new FileOutputStream(new File("/home/rkvac/rkvac_web/settings.dat"));
            ObjectOutputStream o = null;
            o = new ObjectOutputStream(f);
            o.writeObject(settings);
            f.close();
            o.close();
            WebController.inCycles = true;
        } catch (IOException e) {
            e.printStackTrace();
            model.addAttribute("message", "Failed to enable verification. Please check system logs." );
            return "settings-err";
        }

        model.addAttribute("message", "Verification successfully enabled.");
        return "settings-ok";
        //return "redirect:/admin/settings";
    }

    //@ResponseBody
    @GetMapping("settings/restart")
    public String reboot(Model model)  {
        try {
            String[] commands = { "/bin/bash", "-c", "sleep 1 && systemctl restart rkvac-verifier.service" };
            Process process = Runtime.getRuntime().exec(commands);
        } catch (IOException e) {
            e.printStackTrace();
            model.addAttribute("message", "Can´t restart the service! Please check system logs.");
            return "settings-error";
        }finally {
            return "restart-progress";
        }
    }

    @PostMapping("parameters/upload")
    public String singleFileUpload(@RequestParam("file") MultipartFile file,
                                   Model model) {
        File ie_sk = new File("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ie_sk.dat");
        File ra_pk = new File("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ra_pk.dat");
        File ra_public_parameters = new File("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ra_public_parameters.dat");



        try {
            if (file.getOriginalFilename().equals("ra_pk.dat") || file.getOriginalFilename().equals("ie_sk.dat") || file.getOriginalFilename().equals("ra_public_parameters.dat")){
                System.out.println("\n"+new Date()+" Uploading file " + file.getOriginalFilename());


                byte[] bytes = file.getBytes();
                Path path = Paths.get("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/" + file.getOriginalFilename());
                //Path path = Paths.get("C:\\Users\\Bromy\\OneDrive\\Dokumenty\\copied\\" + file.getOriginalFilename());
                Files.write(path, bytes);

                model.addAttribute("status", "ok");
                model.addAttribute("message",
                        "You successfully uploaded '" + file.getOriginalFilename() + "' <br>Please restart the service.");
            }
            else {
                model.addAttribute("status", "error");
                model.addAttribute("message",
                        "Error... '"+ file.getOriginalFilename() + "' isn´t a valid file! Please check file name.");
            }

            if (ie_sk.exists()){
                model.addAttribute("ie_sk", "Found");
            }
            else{
                model.addAttribute("ie_sk", "Not found");
            }
            if (ra_pk.exists()){
                model.addAttribute("ra_pk","Found");
            }
            else {
                model.addAttribute("ra_pk","Not found");
            }
            if (ra_public_parameters.exists()){
                model.addAttribute("ra_pub","Found");
            }
            else{
                model.addAttribute("ra_pub","Not found");
            }

            if (file.isEmpty()) {
                model.addAttribute("message", "Please select a file to upload");
                model.addAttribute("status", "empty");
                return "upload-status";
            }




        } catch (IOException e) {
            e.printStackTrace();
        }

        return "upload-status";
    }




    @GetMapping("parameters/uploadStatus")
    public String uploadStatus(Model model) {
        File ie_sk = new File("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ie_sk.dat");
        File ra_pk = new File("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ra_pk.dat");
        File ra_public_parameters = new File("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ra_public_parameters.dat");

        if (ie_sk.exists()){
            model.addAttribute("ie_sk", "Found");
        }
        else{
            model.addAttribute("ie_sk", "Not found");
        }
        if (ra_pk.exists()){
            model.addAttribute("ra_pk","Found");
        }
        else {
            model.addAttribute("ra_pk","Not found");
        }
        if (ra_public_parameters.exists()){
            model.addAttribute("ra_pub","Found");
        }
        else{
            model.addAttribute("ra_pub","Not found");
        }

        model.addAttribute("message", "Please select a file to upload");
        model.addAttribute("status", "empty");
        return "upload-status";
    }

    @GetMapping("parameters/ie_sk_del")
    public String ieskDel(Model model) {
        File ie_sk = new File("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ie_sk.dat");
       ie_sk.delete();
        System.out.println("\n"+new Date() +" Deleting ie_sk.dat");
        model.addAttribute("status", "delete");
        model.addAttribute("message", "You successfully deleted 'ie_sk.dat'.");
        return "upload-status";

    }
    @GetMapping("parameters/ra_pk_del")
    public String rapk(Model model) {
        File ra_pk = new File("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ra_pk.dat");
        ra_pk.delete();
        System.out.println("\n"+new Date() +" Deleting ra_pk.dat");
        model.addAttribute("status", "delete");
        model.addAttribute("message", "You successfully deleted 'ra_pk.dat'.");
        return "upload-status";
    }
    @GetMapping("parameters/ra_pub_params_del")
    public String rapubparamsDel(Model model) {
        File ra_public_parameters = new File("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ra_public_parameters.dat");
        ra_public_parameters.delete();
        System.out.println("\n"+new Date() +" Deleting ra_public_parameters.dat");
        model.addAttribute("status", "delete");
        model.addAttribute("message", "You successfully deleted 'ra_public_parameters.dat'.");
        return "upload-status";
    }

    @RequestMapping(path = "parameters/download-iesk", method = RequestMethod.GET)
    public ResponseEntity<Resource> downloadIESK(String param) throws IOException {

        File ie_sk = new File("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ie_sk.dat");

        InputStreamResource resource = new InputStreamResource(new FileInputStream(ie_sk));
        HttpHeaders header = new HttpHeaders();
        header.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=ie_sk.dat");

        return ResponseEntity.ok()
                .headers(header)
                .contentLength(ie_sk.length())
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .body(resource);
    }

    @RequestMapping(path = "parameters/download-rapk", method = RequestMethod.GET)
    public ResponseEntity<Resource> downloadRAPK(String param) throws IOException {

        File ra_pk = new File("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ra_pk.dat");

        InputStreamResource resource = new InputStreamResource(new FileInputStream(ra_pk));
        HttpHeaders header = new HttpHeaders();
        header.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=ra_pk.dat");

        return ResponseEntity.ok()
                .headers(header)
                .contentLength(ra_pk.length())
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .body(resource);
    }

    @RequestMapping(path = "parameters/download-ra-pub-params", method = RequestMethod.GET)
    public ResponseEntity<Resource> downloadRAPUBPARAMS(String param) throws IOException {

        File ra_public_parameters = new File("/home/rkvac/rkvac_web/rkvac-protocol/build/data/Verifier/ra_public_parameters.dat");

        InputStreamResource resource = new InputStreamResource(new FileInputStream(ra_public_parameters));
        HttpHeaders header = new HttpHeaders();
        header.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=ra_public_parameters.dat");

        return ResponseEntity.ok()
                .headers(header)
                .contentLength(ra_public_parameters.length())
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .body(resource);
    }

    @RequestMapping(path = "list/download-database", method = RequestMethod.GET)
    public ResponseEntity<Resource> downloadDatabase(String param) throws IOException {

        File database = new File("/home/rkvac/rkvac_web/credentials.dat");

        InputStreamResource resource = new InputStreamResource(new FileInputStream(database));
        HttpHeaders header = new HttpHeaders();
        header.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=credentials.dat");

        return ResponseEntity.ok()
                .headers(header)
                .contentLength(database.length())
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .body(resource);
    }

    @RequestMapping(path = "/download-log", method = RequestMethod.GET)
    public ResponseEntity<Resource> downloadLog(String param, Model model) {
        String pattern = "dd-MM-yyyy";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);

        String dateFormated = simpleDateFormat.format(new Date());
        String path = "/home/rkvac/rkvac_web/logs/verifier_"+dateFormated+".log";
        File database = new File(path);

        InputStreamResource resource = null;
        try {
            resource = new InputStreamResource(new FileInputStream(database));
        } catch (FileNotFoundException e) {
            System.out.println("\n"+ new Date()+" Downloading log" +" /home/rkvac/rkvac_web/logs/verifier_"+dateFormated+".log failed, file not found.");
        }
        HttpHeaders header = new HttpHeaders();
        String name = "attachment; filename="+"verifier_"+dateFormated+".log";
        header.add(HttpHeaders.CONTENT_DISPOSITION, name);

        return ResponseEntity.ok()
                .headers(header)
                .contentLength(database.length())
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .body(resource);
    }

    public static boolean isValidInet4Address(String ip)
    {
        try {
            return Inet4Address.getByName(ip)
                    .getHostAddress().equals(ip);
        }
        catch (UnknownHostException ex) {
            return false;
        }
    }


}
