/*
 AnycastSiteLoad

 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 6 mandatory inputs about anycast and load. It generates the per-site load in every 5 seconds.
 This program is also dependent on the generated dat file by load_parser or ParsingLoad program.
 This program is also dependent on the outputs generated by ParsingDdosLoad program.

 Sample command format: java -jar AnycastSiteLoad.java [No. of sites] [SITES] [CATCHMENT_DIR] [CATCHMENT_DATE] [LOAD_DIRECTORY] [LOAD_DATE]
 
 Sample command:
 java -jar AnycastSiteLoad.jar 3 BOS,ATL,MSN /Path_Prepending_BOS,ATL,MSN_2020-05-29-HITLIST_20191127/2020-05-29-BOS,ATL,MSN/ 2020-05-29 
 /Load_attacks/load-test-new/ 2021-05-28

 Sample output:
 Sample output file will be generated in the CATCHMENT_DIR. 

 Sample output format:
 time site1 packets1 bytes1 site2 packets1 bytes1...
 */
package anycastsiteload;

import java.io.IOException;
import java.io.FileNotFoundException;
import java.util.Iterator;
import java.util.List;
import java.io.FileWriter;
import java.text.DecimalFormat;
import java.util.regex.Pattern;
import java.util.Collections;
import java.util.ArrayList;
import java.io.File;
import java.io.Reader;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.HashMap;

public class AnycastSiteLoad {

    public static void printInstruction() {
        System.out.println(" Description: This code takes 6 mandatory inputs about anycast and load. It generates the per-site load in every 5 seconds.\n"
                + " This program is also dependent on the generated dat file by load_parser or ParsingLoad program.\n"
                + " This program is also dependent on the outputs generated by ParsingDdosLoad program.\n"
                + "\n"
                + " Sample command format: java -jar AnycastSiteLoad.java [No. of sites] [SITES] [CATCHMENT_DIR] [CATCHMENT_DATE] [LOAD_DIRECTORY] [LOAD_DATE]\n"
                + " \n"
                + " Sample command:\n"
                + " java -jar AnycastSiteLoad.jar 3 BOS,ATL,MSN /Path_Prepending_BOS,ATL,MSN_2020-05-29-HITLIST_20191127/2020-05-29-BOS,ATL,MSN/ 2020-05-29 \n"
                + " /Load_attacks/load-test-new/ 2021-05-28\n"
                + "\n"
                + " Sample output:\n"
                + " Sample output file will be generated in the CATCHMENT_DIR. \n"
                + "\n"
                + " Sample output format:\n"
                + " time site1 packets1 bytes1 site2 packets1 bytes1...");
    }

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

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

        final HashMap<String, String> prefixToCatchment = new HashMap<String, String>();
        for (int i = 0; i < NUMBER_OF_SITES; ++i) {
            System.out.println("CURRENT SITE: " + SITES[i]);
            final FileReader fileReader = new FileReader(DIRECTORY + DATE + "." + SITES[i] + ".dat");
            final BufferedReader bufferedReader = new BufferedReader(fileReader);
            String line = "";
            while ((line = bufferedReader.readLine()) != null) {
                if (!line.contains("not-specified")) {
                    continue;
                }
                final String[] splitted = line.split("\\|");
                final String ip = splitted[2];
                final String prefix = ip.substring(0, ip.lastIndexOf("."));
                if (prefixToCatchment.containsKey(prefix)) {
                    prefixToCatchment.put(prefix, "multiple");
                } else {
                    prefixToCatchment.put(prefix, SITES[i]);
                }
            }
        }

        final File folder = new File(LOAD_DIR);
        final File[] listOfFiles = folder.listFiles();
        double t = 5.0;
        final double timeThreshold = 5.0;
        final List<Integer> sortedFileNames = new ArrayList<Integer>();
        for (final File file : listOfFiles) {
            if (file.getName().endsWith("txt")) {
                sortedFileNames.add(Integer.parseInt(file.getName().split("\\.")[0]));
            }
        }
        Collections.sort(sortedFileNames);
        for (final Integer num : sortedFileNames) {
            final File file2 = new File(LOAD_DIR + num + ".txt");
            System.out.println(file2.getName());
            if (file2.isFile()) {
                final FileReader fileReader2 = new FileReader(file2);
                final BufferedReader bufferedReader2 = new BufferedReader(fileReader2);
                final HashMap<String, Long> siteToCount = new HashMap<String, Long>();
                final HashMap<String, Long> siteToBytes = new HashMap<String, Long>();
                String line2 = bufferedReader2.readLine();
                while ((line2 = bufferedReader2.readLine()) != null) {
                    if (line2.contains("#")) {
                        continue;
                    }

                    final String[] splitted2 = line2.split("\t");
                    if (splitted2.length < 2) {
                        continue;
                    }
                    final String prefix2 = splitted2[0];
                    final long load = Long.parseLong(splitted2[1]);
                    long bytes;
                    if (Pattern.matches("\\d+.\\d+.*", splitted2[2])) {
                        bytes = (long) Double.parseDouble(splitted2[2]);
                    } else {
                        bytes = Long.parseLong(splitted2[2]);
                    }
                    String site = "-";
                    if (prefixToCatchment.containsKey(prefix2)) {
                        site = prefixToCatchment.get(prefix2);
                    }
                    if (siteToCount.containsKey(site)) {
                        siteToCount.put(site, siteToCount.get(site) + load);
                        siteToBytes.put(site, siteToBytes.get(site) + bytes);
                    } else {
                        siteToCount.put(site, load);
                        siteToBytes.put(site, bytes);
                    }
                }

                String str = "";
                if (!siteToCount.containsKey("-")) {
                    str = str + t + "\t-\t0.0\t0.0";
                } else {
                    str = str + t + "\t-\t" + new DecimalFormat("#.####").format(siteToCount.get("-") / timeThreshold) + "\t" + new DecimalFormat("#.####").format(siteToBytes.get("-") / timeThreshold);
                }
                for (int j = 0; j < NUMBER_OF_SITES; ++j) {
                    final String site2 = SITES[j];
                    if (!siteToCount.containsKey(SITES[j])) {
                        str = str + "\t" + site2 + "\t0.0\t0.0";
                    } else {
                        str = str + "\t" + site2 + "\t" + new DecimalFormat("#.####").format(siteToCount.get(site2) / timeThreshold) + "\t" + new DecimalFormat("#.####").format(siteToBytes.get(site2) / timeThreshold);
                    }
                }
                if (!siteToCount.containsKey("multiple")) {
                    str += "\tmultiple\t0.0\t0.0";
                } else {
                    str = str + "\tmultiple\t" + new DecimalFormat("#.####").format(siteToCount.get("multiple") / timeThreshold) + "\t" + new DecimalFormat("#.####").format(siteToBytes.get("multiple") / timeThreshold);
                }
                final FileWriter fileWriter = new FileWriter(DIRECTORY + DATE + "-load-" + LOAD_DATE + "-ingress.txt", true);
                fileWriter.write("\n" + str);
                fileWriter.close();
                t += timeThreshold;
            }
        }
    }
}
