package be.iminds.ilabt.jfed.ui.commandline.scanner;

/**
 * CommandLineClient
 */
public class ServerScanner {
//
    //TODO: complete the reimplemtation below if this is ever needed.

//    public static void help(Options options) {
//        HelpFormatter formatter = new HelpFormatter();
//        formatter.printHelp(200, "jfed-scanner-cli [options ... ] <server url or urn> [<server url or urn> ...]", "Possible options:", options, "");
//    }
//
//    @SuppressWarnings("unchecked")
//    public static void main(String[] args) throws JFedException, IOException {
//        BaseCli baseCli = new BaseCli(System.err);
//
//        CommandLineParser parser = new BasicParser();
//
//        // create the Options
//        Options options = new Options();
//        BaseCli.addUserConfig(options, "get user authentication info from the provided context properties file (same format as used by automated tester. Test authority is ignored.)", true);
////        options.addOption("k", "key-file", true, "file containing user certificate and key in PEM format");
////        options.addOption(OptionBuilder.withLongOpt("context-file")
////                .withDescription("get user authentication info from the provided context properties file (same format as used by automated tester. Test authority is ignored.)")
////                .hasArg()
////                .withArgName("CONTEXT_FILE")
////                .create());
//        options.addOption(OptionBuilder.withLongOpt("output-file")
//                .withDescription("The xml file to write the xml description of the scanned servers to. Default: write to stdout")
//                .hasArg()
//                .withArgName("OUTPUT XML FILE")
//                .create());
//        options.addOption("q", "quiet", false, "less output");
//        options.addOption("d", "debug", false, "extra debugging output");
//        options.addOption("U", "accept-getversion-without-urn", false, "Accept info from GetVersion call replies that return no URN.");
//
//        CommandLine line = null;
//        try {
//            // parse the command line arguments
//            line = parser.parse(options, args);
//        } catch (ParseException exp) {
//            System.err.println("Command line argument Syntax error: " + exp.getMessage());
//            help(options);
//            System.exit(1);
//        }
//
//        boolean debug = line.hasOption("debug");
//        boolean acceptGetversionWithoutUrn = line.hasOption("accept-getversion-without-urn");
//        String outputfile = line.getOptionValue("output-file");
//        boolean silent = line.hasOption("quiet");
////        String pemKeyCertFilename = line.getOptionValue("key-file");
////        String contextProperties = line.getOptionValue("context-file");
//
//        baseCli.initAuthoritiesModule(line);
//        try {
//            baseCli.initUserModule(line, System.out, System.err, System.in);
//        } catch (BaseCli.CliArgumentException e) {
//            help(options);
//            //User has been informed already
//            System.exit(1);
//            return;
//        }
//
//        List<String> arguments = (List<String>)line.getArgList();
//        if (arguments.size() < 1) {
//            System.err.println("No URN or urls specified.");
//            String inputs = IOUtils.askCommandLineInput("Give a list of space seperated inputs");
//            String[] in = inputs.split(" ");
//            for (String i : in)
//                arguments.add(i);
//            if (arguments.size() < 1) {
//                System.err.println("Error: No URN or urls specified.");
//                help(options);
//                System.exit(1);
//            }
//        }
//
//
////        SfaAuthority.debug = false; //ugly hack to suppress output
//        Logger logger = new Logger();
//
//        JFedPreferences jFedPreferences = new JFedCorePreferences();
//        AggregateManager2 am2 = new AggregateManager2(logger, jFedPreferences);
//        AggregateManager3 am3 = new AggregateManager3(logger, jFedPreferences);
//        ProtogeniSliceAuthority sa = new ProtogeniSliceAuthority(logger, jFedPreferences);
//
//        GeniUser user = baseCli.getInjector(System.err).getInstance(GeniUser.class);
//
//        if (!BaseCli.checkUser(user, line, System.out, System.err, System.in))
//            System.exit(1);
//
//        List<String> failedScans = new ArrayList<String>();
//        List<Server> resultAuthorities = new ArrayList<Server>();
//        for (String argument : arguments) {
//            List<String> serverBases = new ArrayList<String>();
//            List<URL> urlsToStart = new ArrayList<URL>();
//            if (GeniUrn.valid(argument)) {
//                String tla = GeniUrn.parse(argument).getEncodedTopLevelAuthority();
//                serverBases.add(tla);
//                serverBases.add(tla + ":12369"); //protogeni default
//                serverBases.add(tla + ":11443"); //exogeni port
//            }
//            try {
//                URL argUrl = new URL(argument);
//                urlsToStart.add(argUrl);
//                String host = argUrl.getHost();
//                if (argUrl.getPort() == -1)
//                    serverBases.add(host);
//                else
//                    serverBases.add(host + ":" + argUrl.getPort());
//            } catch (MalformedURLException e) { /*ignore*/ }
//
//            //if not url of urn, use it as serverbase if it doesn't contain special chars
//            if (serverBases.isEmpty() && argument.matches("[-a-zA-Z_.:0-9]*")) {
//                serverBases.add(argument);
//            }
//
//            for (String serverBase : serverBases) {
//                //remove boss. or www. from serverbase
//                if (serverBase.startsWith("boss."))
//                    serverBase = serverBase.substring(5);
//                if (serverBase.startsWith("www."))
//                    serverBase = serverBase.substring(4);
//
//                String wwwServerBase = "www." + serverBase;
//                String bossServerBase = "boss." + serverBase;
//
//                //no www.boss or boss.www
//                if (serverBase.startsWith("www.") || serverBase.startsWith("boss."))
//                    wwwServerBase = serverBase;
//                if (serverBase.startsWith("boss.") || serverBase.startsWith("www."))
//                    bossServerBase = serverBase;
//
//                try {
//                    urlsToStart.add(new URL("https://" + wwwServerBase + "/protogeni/xmlrpc/am/2.0"));
//                    urlsToStart.add(new URL("https://" + serverBase + "/RPC2"));
//                    urlsToStart.add(new URL("https://" + serverBase + "/orca/xmlrpc"));
//                    urlsToStart.add(new URL("https://" + wwwServerBase + "/protogeni/xmlrpc/am/3.0"));
//                    urlsToStart.add(new URL("https://" + wwwServerBase + "/protogeni/xmlrpc/am"));
//                    urlsToStart.add(new URL("https://" + serverBase + "/protogeni/xmlrpc/am/2.0"));
//                    urlsToStart.add(new URL("https://" + serverBase + "/protogeni/xmlrpc/am/3.0"));
//                    urlsToStart.add(new URL("https://" + serverBase + "/protogeni/xmlrpc/am"));
//                    urlsToStart.add(new URL("https://" + bossServerBase + "/protogeni/xmlrpc/am/2.0"));
//                    urlsToStart.add(new URL("https://" + bossServerBase + "/protogeni/xmlrpc/am/3.0"));
//                    urlsToStart.add(new URL("https://" + bossServerBase + "/protogeni/xmlrpc/am"));
//                } catch (MalformedURLException e) { /*ignore*/ }
//            }
//
//            if (debug) {
//                System.out.println("List of URL guesses for '" + argument + "': ");
//                for (URL url : urlsToStart)
//                    System.out.println("    " + url);
//            }
//
//            if (urlsToStart.isEmpty())
//                System.err.println("No URL's can be guessed for '" + argument + "'");
//
//            for (URL urlToTry : urlsToStart) {
//                if (debug)
//                    System.out.println("Trying url: " + urlToTry.toExternalForm());
//
//                //first see if IP resolves
//                try {
//                    InetAddress[] ips = InetAddress.getAllByName(urlToTry.getHost());
//                    if (ips == null || ips.length == 0) {
//                        if (debug)
//                            System.out.println("   Skipping: URL hostname does not resolve: \"" + urlToTry.getHost() + "\"   -> ips=" + ips);
//                        continue;
//                    }
//                } catch (UnknownHostException e) {
//                    if (debug)
//                        System.out.println("   Skipping: URL hostname does not resolve: \"" + urlToTry.getHost() + "\"   -> " + e.getMessage());
//                    continue;
//                }
//
//                //TODO: do not run getCertificateInfo again for same server hostname+port combination
//                if (debug)
//                    System.out.println("   calling SSLCertificateDownloader.getCertificateInfo");
//                SSLCertificateDownloader.SSLCertificateJFedInfo info =
//                        SSLCertificateDownloader.getCertificateInfo(urlToTry);
//
//                if (debug) {
//                    System.out.println("   SSLCertificateDownloader.getCertificateInfo returns");
//                    System.out.println("      urn=" + info.getUrn());
//                    System.out.println("      subject=" + info.getSubject());
//                    System.out.println("      selfSigned=" + info.isSelfSigned());
//                    System.out.println("      subjectMatchesHostname=" + info.getSubjectMatchesHostname());
//                    System.out.println("      urnAuthPart=" + info.getUrnAuthPart());
//                }
//
//                String urn = info.getUrn();
//                if (info.getUrn() == null) {
//                    urn = "urn:publicid:IDN+" + urlToTry.getHost() + "+authority+cm";
//                    System.err.println("The URN of the server could not be determined from the certificate. Using placeholder URN for now: " + urn);
//                }
//
//                TestbedBuilder testbedBuilder = new TestbedBuilder();
//                ServerBuilder serverBuilder = new ServerBuilder();
//                testbedBuilder.addServerBuilder(serverBuilder);
//                testbedBuilder.setLongName(info.getSubject());
//                serverBuilder.setName(info.getSubject());
//                testbedBuilder.setDefaultComponentManagerUrn(urn);
//                serverBuilder.setDefaultComponentManagerUrn(urn);
//
//                ServiceBuilder serviceBuilder = new ServiceBuilder();
//                serviceBuilder.setApi(ApiInfo.ApiName.GENI_AM.getId());
//                serviceBuilder.setApiVersion("2");
//                serviceBuilder.setUrl(urlToTry.toExternalForm());
//                serviceBuilder.setUrn(urn);
//                serverBuilder.addServiceBuilder(serviceBuilder);
//
//
//                if (info.getCert() != null) {
//                    serverBuilder.setCertificateChain(KeyUtil.x509certificateToPem(info.getCert()));
//
//                    if (!info.getSubjectMatchesHostname()) {
//                        if (debug)
//                            System.out.println("Note: Server certificate subject name is not for \"" + urlToTry.getHost() + "\" but for \"" + info.getSubject() + ". Trusting anyway!");
//                        serverBuilder.setAllowedCertificateAlias(info.getSubject());
//                    }
//                }
//
//                testbedBuilder.setId("scanning");
//                serverBuilder.setId(-1);
//                serviceBuilder.setId(-1);
//                Testbed scannedTestbed = testbedBuilder.create();
//                Server scannedServer = scannedTestbed.getServers().get(0);
//                Service scannedService = scannedServer.getServices().get(0);
//
//                ConnectionBuilder connectionBuilder = new BasicConnectionBuilderFactory().createConnectionBuilder();
//                connectionBuilder.setDebugInfo(new JFedConnection.DebugInfo(false, scannedService, user));
//                connectionBuilder.setProxy(null);
//                connectionBuilder.setUrl(urlToTry);
//                connectionBuilder.useHttps(new JFedTrustStore(scannedServer), null/*handleUntrustedCallback*/);
//                connectionBuilder.useSslClientAuthentication(user.getClientCertificateChain(), user.getPrivateKey());
//                SfaConnection con = connectionBuilder.buildSfaConnection();
//
//
//                if (debug)
//                    System.out.println("   calling AMv2 GetVersion");
//                AggregateManager2.AggregateManagerReply<AggregateManager2.VersionInfo> versionInfoReply = null;
//                try {
//                    //call getversion. If this fails, an exception is thrown, and we will call next url
//                    versionInfoReply = am2.getVersion(con);
//
//                    if (!versionInfoReply.getGeniResponseCode().isSuccess()) continue; //try next url
//
//                    AggregateManager2.VersionInfo versionInfo = versionInfoReply.getValue();
//
//                    if (versionInfo == null) continue; //try next url
//
//                    if (debug)
//                        System.out.println("   AMv2 GetVersion returned a usable result");
//
//                    String newHrn = versionInfo.getExtra("hrn");
//                    if (newHrn != null) {
//                        testbedBuilder.setLongName(newHrn);
//                        serverBuilder.setName(newHrn);
//                    }
//
//                    String newUrn = versionInfo.getExtra("urn");
//                    if (newUrn != null) {
//                        testbedBuilder.setDefaultComponentManagerUrn(newUrn);
//                        serverBuilder.setDefaultComponentManagerUrn(newUrn);
//                        serviceBuilder.setUrn(newUrn);
//                    } else {
//                        if (acceptGetversionWithoutUrn)
//                            System.out.println("     AMv2 GetVersion returned a usable result, without urn: using result. "); //TODO warn that URN is guessed in this case!
//                        else {
//                            System.out.println(" ************************ AMv2 GetVersion returned a usable result, without urn: not using result. ************************ ");
//                            continue;
//                        }
//                    }
//
//                    for (AggregateManager2.VersionInfo.VersionPair apiVersion : versionInfo.getApiVersions()) {
//                        try {
//                            URL versionUrl = new URL(apiVersion.getUrl());
//                            if (versionUrl.getHost().equals("localhost")) {
//                                System.err.println("WARNING: Aggregate Manager returned URL containing \"localhost\" in GetVersion result: " + apiVersion.getUrl() + "   (automatically fixing url using the URL you supplied)");
//                                versionUrl = new URL(apiVersion.getUrl().replace("localhost", urlToTry.getHost()));
//                            }
//                            if (versionUrl.getProtocol().equals("http")) {
//                                System.err.println("Note: Server gave URL with http instead of https: \"" + apiVersion.getUrl() + "\". Will change it to https!");
//
//                                //change http to https
//                                versionUrl = new URL(versionUrl.toString().replace("http://", "https://"));
//                            }
//
//
//                            ServiceBuilder extraServiceBuilder = new ServiceBuilder();
//                            serviceBuilder.setApi(ApiInfo.ApiName.GENI_AM.getId());
//                            serviceBuilder.setApiVersion("2");
//                            serviceBuilder.setUrl(urlToTry.toExternalForm());
//                            serviceBuilder.setUrn(urn);
//                            serverBuilder.addServiceBuilder(serviceBuilder);
//
//                            urlMap.put(new ApiInfo.Api(ApiInfo.ApiName.GENI_AM, apiVersion.getVersionNr()), versionUrl);
//                        } catch (MalformedURLException e) {
//                            if (!silent)
//                                System.err.println("Error: Aggregate Manager returned malformed URL in GetVersion result: \"" + apiVersion.getUrl() + "\"");
//                        }
//                    }
//
//                    //TODO perhaps check if advertised URL for this version is same as known/scanned.
//                    if (urlMap.isEmpty()) {
//
//
//                        //fall back to version at this URL only (should be known when GetVersion successful)
//                        int versionNr = versionInfo.getApi();
//                        ServerType st = new ApiInfo.Api(ApiInfo.ApiName.GENI_AM, versionNr);
//                        urlMap.put(st, urlToTry);
//                        scannedGeniAuthority.replaceUrls(urlMap);
//
//                        //TODO might want to keep trying, to see if there are better URL's for GetVersion
//                    } else
//                        scannedGeniAuthority.replaceUrls(urlMap);
//
//                    //success, so stop trying urls
//                    resultAuthorities.add(scannedGeniAuthority);
//
//                    if (debug)
//                        System.out.println("   url successfully scanned. Saving result and not trying next url. urn=" + scannedGeniAuthority.getDefaultComponentManagerUrn() + "\n\n\n");
//                    break;
//                } catch (JFedException e) {
//                    if (debug) {
//                        System.out.println("   error, will skip url. " + e.getClass().getName() + "  " + e.getMessage());
//                        e.printStackTrace();
//                    }
//                    //try next URL
//                    continue;
//                }
//            }
//
//            //failed to scan
//            failedScans.add(argument);
//        }
//
//        if (debug) System.out.println("Printing results:");
//        if (!failedScans.isEmpty()) {
//            System.err.println("Scan failed for the following arguments:");
//            for (String failedScan : failedScans)
//                System.err.println("    " + failedScan);
//        }
//        TestbedInfoSource model = new AuthorityListModel();
//        for (Server resAuth : resultAuthorities) {
//            model.addAuthority(resAuth);
//        }
//        System.out.println(StoredTestbedInfo.toXml(model));
//        System.exit(0);
//    }
}
