/*
 ParsingLoad

 Copyright (C) 2022 by University of Southern California
 Written by ASM Rizvi<asmrizvi@usc.edu>

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License,
 version 2, as published by the Free Software Foundation.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License along
 with this program; if not, write to the Free Software Foundation, Inc.,
 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 
 */

 /* 
 Description: This code takes inputs about the data files in pcap format, parses them, and generates files for catchment and load distribution. 
 This program is dependent on pingextract to translate the pcap files into .dat files.
 Sample command format: java -jar ParsingLoad.jar [N_SITES] [SITES] [DEST_DIR] [OUTPUT_DIR] [DATE] [LOAD] [LOAD_DATE] [HITLIST]
 Sample command:
 java -jar ParsingLoad.jar 3 BOS,SLC,SEA2 /Path_Prepending_BOS,SLC,SEA2_2020-02-28-HITLIST_20191127/2020-02-28-BOS,SLC,SEA2-BOS1/ 
 /Path_Prepending_BOS,SLC,SEA2_2020-02-28-HITLIST_20191127/2020-02-28-BOS,SLC,SEA2-BOS1/ 2020-02-28 /loads/load.txt 2022-02-06 ip_list_20191127.txt
 Sample output: Generated .dat files in the OUTPUT_DIR
 Sample output format: file names will indicate the site name, and inside each file we will get the IP to map prefix to site catchment.
 */
package parsingload;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.HashMap;

public class ParsingLoad {

    public static void printInstruction() {
        System.out.println(" Description: This code takes inputs about the data files in pcap format, parses them, and generates files for catchment and load distribution. \n"
                + " This program is dependent on pingextract to translate the pcap files into .dat files.\n"
                + " Sample command format: java -jar ParsingLoad.jar [N_SITES] [SITES] [DEST_DIR] [OUTPUT_DIR] [DATE] [LOAD] [LOAD_DATE] [HITLIST]\n"
                + " Sample command:\n"
                + " java -jar ParsingLoad.jar 3 BOS,SLC,SEA2 /Path_Prepending_BOS,SLC,SEA2_2020-02-28-HITLIST_20191127/2020-02-28-BOS,SLC,SEA2-BOS1/ \n"
                + " /Path_Prepending_BOS,SLC,SEA2_2020-02-28-HITLIST_20191127/2020-02-28-BOS,SLC,SEA2-BOS1/ 2020-02-28 /loads/load.txt 2022-02-06 ip_list_20191127.txt\n"
                + " Sample output: Generated .dat files in the OUTPUT_DIR\n"
                + " Sample output format: file names will indicate the site name, and inside each file we will get the IP to map prefix to site catchment.");
    }

    public static void main(String[] args) throws FileNotFoundException, IOException, InterruptedException {
        if (args.length < 7) {
            System.out.println("===============Not enough parameters to run the program=============");
            printInstruction();
            return;
        }

        int NUMBER_OF_SITES = Integer.parseInt(args[0]);
        String[] SITES = args[1].split(",");
        String BASEDIR = args[2];
        String DIRECTORY = args[3];
        String DATE = args[4];
        String LOAD_DIR = args[5];
        String LOAD_DATE = args[6];
        String HITLIST = "ip_list_20191127.txt";

        if (args.length == 8) {
            HITLIST = args[7];
        }

        FileReader fileReader = new FileReader(HITLIST);
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        String line = bufferedReader.readLine();
        HashMap<String, String> targets = new HashMap<>();
        while ((line = bufferedReader.readLine()) != null) {
            String prefix = line.substring(0, line.lastIndexOf("."));
            if (!targets.containsKey(prefix)) {
                targets.put(prefix, "-");
            }
        }
        for (int i = 0; i < NUMBER_OF_SITES; i++) {
            System.out.println("CURRENT SITE: " + SITES[i]);
            File file = new File(DIRECTORY + DATE + "." + SITES[i] + ".dat");
            if (!file.exists()) {
                String source = DIRECTORY + DATE + "-" + SITES[i] + ".pcap";
                String dest = DIRECTORY + DATE + "." + SITES[i] + ".dat";
                Process process = Runtime.getRuntime().exec("sh run_pingextract.sh " + source + " " + dest);
                process.waitFor();
            }
            fileReader = new FileReader(DIRECTORY + DATE + "." + SITES[i] + ".dat");
            bufferedReader = new BufferedReader(fileReader);
            while ((line = bufferedReader.readLine()) != null) {
                if (!line.contains("not-specified")) {
                    continue;
                }
                String[] splitted = line.split("\\|");
                String ip = splitted[2];
                String prefix = ip.substring(0, ip.lastIndexOf("."));
                if (targets.containsKey(prefix)) {
                    if (((String) targets.get(prefix)).equals("-")) {
                        targets.put(prefix, SITES[i]);
                        continue;
                    }
                    if (!((String) targets.get(prefix)).equals(SITES[i])) {
                        targets.put(prefix, "multiple");
                    }
                    continue;
                }
                targets.put(prefix, SITES[i]);
            }
        }
        double total = 0.0D;
        double totalReplies = 0.0D;
        HashMap<String, Double> siteToCount = new HashMap<>();
        for (String prefix : targets.keySet()) {
            String site = targets.get(prefix);
            total++;
            if (!site.equals("-")) {
                totalReplies++;
            }
            if (siteToCount.containsKey(site)) {
                siteToCount.put(site, Double.valueOf(((Double) siteToCount.get(site)).doubleValue() + 1.0D));
                continue;
            }
            siteToCount.put(site, Double.valueOf(1.0D));
        }
        String[] newSites = new String[SITES.length + 2];
        newSites[0] = "-";
        int j;
        for (j = 1; j < newSites.length - 1; j++) {
            newSites[j] = SITES[j - 1];
        }
        newSites[newSites.length - 1] = "multiple";
        for (j = 0; j < newSites.length; j++) {
            String site = newSites[j];
            if (!siteToCount.containsKey(site)) {
                siteToCount.put(site, Double.valueOf(0.0D));
            }
            System.out.println("WRITE LOAD: " + site);
            FileWriter fileWriter = new FileWriter(DIRECTORY + DATE + "-catchment-percentage.txt", true);
            FileWriter fileWriter2 = new FileWriter(BASEDIR + "all-" + DATE + "-load-" + LOAD_DATE + ".txt", true);
            if (site.equals("-")) {
                fileWriter.write("\n" + site + " " + (new DecimalFormat("#")).format(siteToCount.get(site)) + " " + (new DecimalFormat("#.####"))
                        .format(((Double) siteToCount.get(site)).doubleValue() / total));
                fileWriter2.write(DIRECTORY + "\n" + site + " " + (new DecimalFormat("#")).format(siteToCount.get(site)) + " " + (new DecimalFormat("#.####"))
                        .format(((Double) siteToCount.get(site)).doubleValue() / total));
            } else {
                fileWriter.write("\n" + site + " " + (new DecimalFormat("#")).format(siteToCount.get(site)) + " " + (new DecimalFormat("#.####"))
                        .format(((Double) siteToCount.get(site)).doubleValue() / total) + " " + (new DecimalFormat("#.####"))
                        .format(((Double) siteToCount.get(site)).doubleValue() / totalReplies));
                fileWriter2.write("\n" + site + " " + (new DecimalFormat("#")).format(siteToCount.get(site)) + " " + (new DecimalFormat("#.####"))
                        .format(((Double) siteToCount.get(site)).doubleValue() / total) + " " + (new DecimalFormat("#.####"))
                        .format(((Double) siteToCount.get(site)).doubleValue() / totalReplies));
            }
            fileWriter.close();
            fileWriter2.close();
        }
        fileReader = new FileReader(LOAD_DIR + "load-" + LOAD_DATE + ".fsdb");
        bufferedReader = new BufferedReader(fileReader);
        HashMap<String, Double> siteToLoad = new HashMap<>();
        double totalLoad = 0.0D;
        double totalRepliedLoad = 0.0D;
        while ((line = bufferedReader.readLine()) != null) {
            if (line.contains("fsdb") || line.contains("#")) {
                continue;
            }

            String[] splitted = line.split("\t");
            if (splitted.length < 2) {
                continue;
            }
            int firstPart = 0;
            int secondPart = 0;
            int thirdPart = 0;

            String octate = splitted[0];
            if (octate.contains(".")) {
                firstPart = Integer.parseInt(octate.split("\\.")[0]);
                secondPart = Integer.parseInt(octate.split("\\.")[1]);
                thirdPart = Integer.parseInt(octate.split("\\.")[2]);
            } else {
                firstPart = Integer.parseInt(octate.substring(0, 2), 16);
                secondPart = Integer.parseInt(octate.substring(2, 4), 16);
                thirdPart = Integer.parseInt(octate.substring(4, 6), 16);
            }

            String prefixForLoad = String.valueOf(firstPart) + "." + String.valueOf(secondPart) + "." + String.valueOf(thirdPart);
            // System.out.println(octate + "\t" + prefixForLoad);
            ;
            String site = targets.get(prefixForLoad);
            if (site == null) {
                site = "-";
            }
            if (siteToLoad.containsKey(site)) {
                siteToLoad.put(site, Double.valueOf(((Double) siteToLoad.get(site)).doubleValue() + Double.parseDouble(splitted[1])));
            } else {
                siteToLoad.put(site, Double.valueOf(Double.parseDouble(splitted[1])));
            }
            totalLoad += Double.parseDouble(splitted[1]);
            if (!site.equals("-")) {
                totalRepliedLoad += Double.parseDouble(splitted[1]);
            }
        }
        for (int k = 0; k < newSites.length; k++) {
            String site = newSites[k];
            if (!siteToLoad.containsKey(site)) {
                siteToLoad.put(site, Double.valueOf(0.0D));
            }
            FileWriter fileWriter = new FileWriter(DIRECTORY + DATE + "-load-percentage.txt", true);
            FileWriter fileWriter2 = new FileWriter(BASEDIR + "all-" + DATE + "-load-" + LOAD_DATE + ".txt", true);
            if (site.equals("-")) {
                fileWriter.write("\n" + site + " " + (new DecimalFormat("#")).format(siteToLoad.get(site)) + " " + (new DecimalFormat("#.####"))
                        .format(((Double) siteToLoad.get(site)).doubleValue() / totalLoad));
                fileWriter2.write("\n" + site + " " + (new DecimalFormat("#")).format(siteToLoad.get(site)) + " " + (new DecimalFormat("#.####"))
                        .format(((Double) siteToLoad.get(site)).doubleValue() / totalLoad));
            } else {
                fileWriter.write("\n" + site + " " + (new DecimalFormat("#")).format(siteToLoad.get(site)) + " " + (new DecimalFormat("#.####"))
                        .format(((Double) siteToLoad.get(site)).doubleValue() / totalLoad) + " " + (new DecimalFormat("#.####"))
                        .format(((Double) siteToLoad.get(site)).doubleValue() / totalRepliedLoad));
                fileWriter2.write("\n" + site + " " + (new DecimalFormat("#")).format(siteToLoad.get(site)) + " " + (new DecimalFormat("#.####"))
                        .format(((Double) siteToLoad.get(site)).doubleValue() / totalLoad) + " " + (new DecimalFormat("#.####"))
                        .format(((Double) siteToLoad.get(site)).doubleValue() / totalRepliedLoad));
            }
            fileWriter.close();
            fileWriter2.close();
        }
    }
}
