import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.charset.Charset;
import java.nio.file.FileSystemException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;

public class Main {

    private static File f = new File(System.getProperty("user.dir") + "\\options.cfg");

    private static Path newFile = Paths.get("options.cfg");
    private static List<String> fileContents;

    private static File homeDir;

    private static Map<String, String> env = System.getenv();

    private static String os = System.getProperty("os.name");

    public static void main(String[] args) {

        if (os.startsWith("Windows")) {
            os = "Windows";
        } else if (os.startsWith("Linux")) {
            os = "Linux";
        } else if (os.startsWith("Mac")) {
            os = "Mac";
        } else {
            System.out.println("WARNING: YOU ARE USING AN UNSUPPORTED OS!!! PLEASE REPORT ON GITHUB ISSUES");
            System.exit(100); // Invalid OS
        }

        if (!f.exists() || f.isDirectory()) {
            // Make file, tell user to restart, stop
            try {
                if (os.equals("Windows")) {
                    Files.write(newFile, Arrays.asList(
                            "## UNCOMMENT THIS IF YOU WANT TO SPECIFY AN INSTALLATION DIRECTORY DIRECTORY. NO ENVIRONMENT VARIABLES!!!. TWO BACKSLASHES!!!##",
                            "## Example: C:\\someDirectory",
                            "# C:\\")
                            , Charset.forName("UTF-8"));
                } else {
                    Files.write(newFile, Arrays.asList(
                            "## UNCOMMENT THIS IF YOU WANT TO SPECIFY AN INSTALLATION DIRECTORY DIRECTORY. NO ENVIRONMENT VARIABLES!!!. TWO BACKSLASHES!!!##",
                            "## Example: ~\\someDirectory",
                            "# ~\\")
                            , Charset.forName("UTF-8"));
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            System.out.println("Please edit config file or restart the program to continue");

            System.exit(0);
        }

        // Read file
        try {
            fileContents = Files.readAllLines(newFile, Charset.defaultCharset());
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Remove first and second lines
        // THIS SHOULD BE CHANGED TO JUST IGNORE ANY LINE WITH A #
        fileContents.remove(0);
        fileContents.remove(0);

        // If line does not start with #, set it as the variable
        File templateDir;

        if (!fileContents.get(0).substring(0, 1).equals("#")) {
            templateDir = new File(fileContents.get(0));
        } else {
            if (os.equals("Windows")) {
                templateDir = new File("C:\\default");
            } else {
                templateDir = new File("~\\default");
            }
        }

        // From: http://stackoverflow.com/questions/10135074/download-file-from-https-server-using-java

        // Create a new trust manager that trust all certificates
        TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }

                    public void checkClientTrusted(
                            java.security.cert.X509Certificate[] certs, String authType) {
                    }

                    public void checkServerTrusted(
                            java.security.cert.X509Certificate[] certs, String authType) {
                    }
                }
        };

        // Activate the new trust manager
        try {
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        } catch (Exception e) {
            e.printStackTrace();
        }

        // Download everything

        download("https://raw.githubusercontent.com/jakebacker/IntelliWPIPlugins/templates/RobotCommand.java");
        download("https://raw.githubusercontent.com/jakebacker/IntelliWPIPlugins/templates/RobotCommandGroup.java");
        download("https://raw.githubusercontent.com/jakebacker/IntelliWPIPlugins/templates/RobotSubsystem.java");

        download("https://github.com/ThomasJClark/netconsole-idea-plugin/releases/download/1.0/NetConsole.jar");
        if (os.equals("Windows")) {
            if (templateDir.getAbsolutePath().equals("C:\\default")) {

                File defaultDir = new File(env.get("USERPROFILE"));
                String[] names = defaultDir.list();
                ArrayList<String> validInstallations = new ArrayList<String>();

                assert names != null;
                for (String name : names) {

                    if (new File(env.get("USERPROFILE") + "\\" + name).isDirectory() && (name.startsWith(".IntelliJIdea") || name.startsWith(".Idea"))) {
                        validInstallations.add(name);
                    }

                }

                Collections.sort(validInstallations, Collections.<String>reverseOrder());

                try {
                    homeDir = new File(env.get("USERPROFILE") + "\\" + validInstallations.get(0));
                    if (!new File(env.get("USERPROFILE") + "\\" + validInstallations.get(0) + "\\config\\fileTemplates").exists()) {
                        System.out.println("Creating Directory");
                        new File(env.get("USERPROFILE") + "\\" + validInstallations.get(0) + "\\config\\fileTemplates").mkdir();
                        defaultDir = new File(env.get("USERPROFILE") + "\\" + validInstallations.get(0) + "\\config\\fileTemplates");
                    }
                } catch (Exception e) {
                    System.out.println("No installations detected!");
                    e.printStackTrace();
                    System.exit(101);
                }

                templateDir = defaultDir;

                copyFilesTo(templateDir);

            } else {
                // Custom directory stuff
                homeDir = templateDir;
                templateDir = new File(templateDir.getAbsolutePath() + "\\config\\fileTemplates");


                System.out.println(templateDir.getAbsolutePath());
                if (!templateDir.isDirectory()) {
                    System.out.println("Invalid Directory!");
                    System.exit(1);
                }

                copyFilesTo(templateDir);

            }
        } else if (os.equals("Linux")) {
            if (templateDir.getAbsolutePath().equals("~\\default")) {

                File defaultDir = new File("~\\");
                String[] names = defaultDir.list();
                ArrayList<String> validInstallations = new ArrayList<String>();

                assert names != null;
                for (String name : names) {

                    if (new File("~\\" + name).isDirectory() && (name.startsWith(".IntelliJIdea") || name.startsWith(".Idea"))) {
                        validInstallations.add(name);
                    }

                }

                Collections.sort(validInstallations, Collections.<String>reverseOrder());

                try {
                    homeDir = new File("~\\" + validInstallations.get(0));
                    defaultDir = new File("~\\" + validInstallations.get(0) + "\\config\\fileTemplates");

                    if (!new File("~\\" + validInstallations.get(0) + "\\config\\fileTemplates").exists()) {
                        System.out.println("Creating Directory");
                        new File("~\\" + validInstallations.get(0) + "\\config\\fileTemplates").mkdir();
                        defaultDir = new File("~\\" + validInstallations.get(0) + "\\config\\fileTemplates");
                    }

                } catch (Exception e) {
                    System.out.println("No installations detected!");
                    e.printStackTrace();
                    System.exit(1);
                }

                templateDir = defaultDir;

                copyFilesTo(templateDir);

            } else {
                // Custom directory stuff
                homeDir = templateDir;
                templateDir = new File(templateDir.getAbsolutePath() + "\\config\\fileTemplates");

                if (!templateDir.isDirectory()) {
                    System.out.println("Invalid Directory!");
                    System.exit(1);
                }

                copyFilesTo(templateDir);

            }
        } else {
            if (templateDir.getAbsolutePath().equals("~\\default")) {

                File defaultDir = new File("~\\Library\\Preferences");
                String[] names = defaultDir.list();
                ArrayList<String> validInstallations = new ArrayList<String>();

                assert names != null;
                for (String name : names) {

                    if (new File("~\\Library\\Preferences" + name).isDirectory() && (name.startsWith("IntelliJIdea") || name.startsWith(".Idea"))) {
                        validInstallations.add(name);
                    }

                }

                Collections.sort(validInstallations, Collections.<String>reverseOrder());

                try {
                    defaultDir = new File("~\\Library\\Preferences\\" + validInstallations.get(0) + "\\fileTemplates");

                    if (!new File("~\\" + validInstallations.get(0) + "\\config\\fileTemplates").exists()) {
                        System.out.println("Creating Directory");
                        new File("~\\" + validInstallations.get(0) + "\\config\\fileTemplates").mkdir();
                        defaultDir = new File("~\\" + validInstallations.get(0) + "\\config\\fileTemplates");
                    }

                } catch (Exception e) {
                    System.out.println("No installations detected!");
                    e.printStackTrace();
                    System.exit(1);
                }

                templateDir = defaultDir;

                copyFilesTo(templateDir);

            } else {
                // Custom directory stuff
                homeDir = templateDir;
                templateDir = new File(templateDir.getAbsolutePath() + "\\fileTemplates");

                if (!templateDir.isDirectory()) {
                    System.out.println("Invalid Directory!");
                    System.exit(1);
                }

                copyFilesTo(templateDir);

            }
        }

        // Setup NetConsole


        if (os.equals("Mac")) {
            try {
                Files.copy(Paths.get("NetConsole.jar"), Paths.get("~\\Library\\Application Support\\plugins\\NetConsole.jar"), REPLACE_EXISTING);
            } catch (FileSystemException e) {
                System.out.println("Could not set up NetConsole. Are you running IntelliJ?");
                e.printStackTrace();
            } catch (IOException ee) {
                ee.printStackTrace();
            }
        } else {
            try {
                Files.copy(Paths.get("NetConsole.jar"), Paths.get(homeDir + "\\config\\plugins\\NetConsole.jar"), REPLACE_EXISTING);
            } catch (FileSystemException e) {
                System.out.println("Could not set up NetConsole. Are you running IntelliJ?");
                e.printStackTrace();
            } catch (IOException ee) {
                ee.printStackTrace();
            }
        }

        // Download project plugin

        // Clean up

        cleanup();
    }

    private static void download(String sSite) {
        try {
            URL site = new URL(sSite);
            ReadableByteChannel rbc = Channels.newChannel(site.openStream());
            FileOutputStream fos = new FileOutputStream(site.toString().substring(site.toString().lastIndexOf("/")+1));
            fos.getChannel().transferFrom(rbc, 0 , Long.MAX_VALUE);
            System.out.println("Downloaded " + site.toString().substring(site.toString().lastIndexOf("/")+1) + " sucessfully!");
            fos.close();
            rbc.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void copyFilesTo(File templateDir) {
        try {
            Files.copy(Paths.get("RobotCommand.java"), Paths.get(templateDir + "\\RobotCommand.java"), REPLACE_EXISTING);
            Files.copy(Paths.get("RobotCommandGroup.java"), Paths.get(templateDir + "\\RobotCommandGroup.java"), REPLACE_EXISTING);
            Files.copy(Paths.get("RobotSubsystem.java"), Paths.get(templateDir + "\\RobotSubsystem.java"), REPLACE_EXISTING);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void cleanup() {
        try {
            Files.delete(Paths.get("RobotCommand.java"));
            Files.delete(Paths.get("RobotCommandGroup.java"));
            Files.delete(Paths.get("RobotSubsystem.java"));
            Files.delete(Paths.get("NetConsole.jar"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
