/* **********************************************************
 * Copyright (c) 2019 VMware, Inc.  All rights reserved.
 * -- VMware Confidential
 * **********************************************************/
package com.vmware.samples.drconfig;

import java.net.MalformedURLException;
import java.net.URL;

/**
 * This is a container object for configurations that are relevant to the
 * configuration manager sample application.
 */
final class CmdOptions
   extends com.vmware.samples.drconfig.BaseOptions {

   private static final IOHelper IO_HELPER;

   static {
      IO_HELPER = System.console() == null ?
                  new StandardIOHelper(System.in, System.out) :
                  new ConsoleIOHelper(System.console());
   }

   /** The LookupService/VC URL used to configure SRM. */
   public final String _lkpUrl;

   /** The Virtual Center user name **/
   public final String _vcUserName;

   /** The Virtual Center user name password **/
   public final String _vcPassword;

   /**
    * Construct a container for the configuration that pertains specifically
    * to this sample application. Used for Configure
    *
    * @param vaAddress Address URL of the Virtual Appliance
    * @param vaUserName Virtual Appliance user name
    * @param vaPassword Virtual Appliance Password
    * @param lkpUrl Lookup Service URL (this could be the same as the VC's URL)
    * @param vcUserName Username used to login into the Virtual Center
    * @param vcPassword Password used for the given username
    * @param ignoreCert The user has requested to ignore SSL certificates in
    *    SRM connections.
    * @param option Operation type
    */
   CmdOptions(
      final URL     vaAddress,
      final String  vaUserName,
      final String  vaPassword,
      final String  lkpUrl,
      final String  vcUserName,
      final String  vcPassword,
      final boolean ignoreCert,
      final String option)
   {
      super(vaAddress, vaUserName, vaPassword, ignoreCert, option);
      _lkpUrl = lkpUrl;
      _vcUserName = vcUserName;
      _vcPassword = vcPassword;
   }

   /**
    * Same comment as above but with different parameters. Used for Get Current Config
    */
   CmdOptions(
         final URL vaAddress,
         final String vaUserName,
         final String vaPassword,
         final boolean ignoreCert,
         final String option)
   {
     super(vaAddress, vaUserName, vaPassword, ignoreCert, option);
     _lkpUrl = null;
     _vcUserName = null;
     _vcPassword = null;
   }

   /**
    * Same comment as above but with different parameters. Used for Clear Config
    */
   CmdOptions(
         final URL vaAddress,
         final String vaUserName,
         final String vaPassword,
         final String vcUserName,
         final String vcPassword,
         final boolean ignoreCert,
         final String option)
   {
     super(vaAddress, vaUserName, vaPassword, ignoreCert, option);
     _lkpUrl = null;
     _vcUserName = vcUserName;
     _vcPassword = vcPassword;
   }

   /**
    * Construct the options encapsulation, performing a (quick-and-dirty) parse
    * of the command-line arguments.
    *
    * @param args The tokenized command-line parameters.
    * @throws ShowHelpThrowable if a "--help" parameter has been specified.
    *    This halts the command-line processing and invalidates the Options
    *    instance.
    * @throws Generic Exception holding a reason
    */
   static CmdOptions parseOptionsConfigure(final String[] args)
      throws CmdOptions.ShowHelpThrowable, Exception {

      boolean ignoreCert = false;
      String operation = null;

      URL vaAddressUrl = null;
      String vaUserName = null;
      String vaPassword = null;
      String servicePath = "/configureserver/sdk";
      String protocol = "https";
      int    portNumber = 5480;

      String pscUrl = null;
      String vcUserName = null;
      String vcPassword = null;

      for (int i = 0; i < args.length; ++i) {
         if (args[i].equals("--help")) {
            throw new ShowHelpThrowable();
         } else if (args[i].equals("--ignorecerts")) {
            ignoreCert = true;
         } else if (args[i].equals("configure")) {
            operation = "configure";
         } else if (args[i].equals("clear")) {
            operation = "clear";
         } else if (args[i].equals("get-config")) {
            operation = "readConfig";
         } else if (args[i].equals("--drconfigaddr")) {
            if (++i == args.length) {
               throw new InvalidCliArgumentException(
                      "--drconfigaddr option requires an argument");
            }
            try {
               if(args[i].contains(":5480/configureserver/sdk")) {
                  vaAddressUrl = new URL(args[i]);
               } else {
                  StringBuffer sb = new StringBuffer();
                  sb.append(protocol);
                  sb.append("://");
                  sb.append(args[i]);
                  sb.append(":");
                  sb.append(portNumber);
                  sb.append(servicePath);

                  vaAddressUrl = new URL(sb.toString());
               }
            } catch (MalformedURLException mue) {
               throw new InvalidCliArgumentException(
                  "Specified URL is malformed -- " + mue.getMessage(), mue);
            }
         } else if (args[i].equals("--drconfiguser")) {
            if (++i == args.length) {
               throw new InvalidCliArgumentException(
                  "--drconfiguser option requires an argument");
            }
            vaUserName = args[i];
         } else if (args[i].equals("--pscuri")) {
            if (++i == args.length) {
               throw new InvalidCliArgumentException(
                  "--pscuri option requires an argument");
            }
            if(args[i].contains(":443")) {
               pscUrl = args[i];
            } else {
               pscUrl = args[i];
               pscUrl.concat(":443");
            }
         } else if (args[i].equals("--pscuser")) {
            if (++i == args.length) {
               throw new InvalidCliArgumentException(
                  "--pscuser option requires an argument");
            }
            vcUserName = args[i];
         } else {
            throw new InvalidCliArgumentException(
               "Invalid argument -- \"" + args[i] + "\"");
         }
      }

      System.out.println("Enter Virtual Appliance password:");
      vaPassword = new String(IO_HELPER.readPass("Password: "));

      if (operation.equals("configure") || operation.equals("clear")) {
         System.out.println("Enter Virtual Center admin password:");
         vcPassword = new String(IO_HELPER.readPass("Password: "));
      }

      if (vaUserName == null || vaUserName.isEmpty() || vaPassword == null || vaPassword.isEmpty() ||
         vaAddressUrl == null) {
         throw new Exception("No username, password or VA Address are provided.");
      }

      if (operation.equals("configure")) {
         if (pscUrl == null) {
            throw new Exception("No arguments for '--uri'");
         }
         if(vcUserName == null || vcUserName.isEmpty() || vcPassword == null || vcPassword.isEmpty()) {
            throw new Exception("No arguments for either username or password for Virtual Center");
         }

         return new CmdOptions(
               vaAddressUrl,
               vaUserName,
               vaPassword,
               pscUrl,
               vcUserName,
               vcPassword,
               ignoreCert,
               "configure");
      } else if (operation.equals("clear")) {
         if(vcUserName == null || vcUserName.isEmpty() || vcPassword == null || vcPassword.isEmpty()) {
            throw new Exception("No arguments for either username or password for Virtual Center");
         }
         return new CmdOptions(
               vaAddressUrl,
               vaUserName,
               vaPassword,
               vcUserName,
               vcPassword,
               ignoreCert,
               "clear");
      } else if (operation.equals("readConfig")) {
         return new CmdOptions(
               vaAddressUrl,
               vaUserName,
               vaPassword,
               ignoreCert,
               "readConfig");
      } else {
         throw new Exception("Unknown operation");
      }
   }

   /**
    * Prints a helpful usage message to the console.
    *
    * @param progName The name of the executable being run.
    */
   public static void printHelp(final String programName) {
         System.out.println("Usage: " + programName + " [command] [options]");
         System.out.println();
         System.out.println("Commands:");
         System.out.println(" configure Configure SRM server");
         System.out.println(" clear Clear SRM server configuration");
         System.out.println(" get-config Get configuration of SRM server");
         System.out.println("Options:");
         System.out.println(" --drconfigaddr DrConfig Service address");
         System.out.println(" --drconfiguser DrConfig Service username");
         System.out.println(" --ignorecerts Skip validation of certificates");
         System.out.println();
         System.out.println("Configure SRM server");
         System.out.println();
         System.out.println("Usage: " + programName + " configure [options]");
         System.out.println();
         System.out.println("Options:");
         System.out.println(" --drconfigaddr DrConfig Service address");
         System.out.println(" --drconfiguser DrConfig Service username");
         System.out.println(" --ignorecerts Skip validation of certificates");
         System.out.println(" --pscuri PSC URI");
         System.out.println(" --pscuser PSC user");
         System.out.println();
         System.out.println("Get configuration of SRM server");
         System.out.println();
         System.out.println("Usage: " + programName + " get-config [options]");
         System.out.println();
         System.out.println("Options:");
         System.out.println(" --drconfigaddr DrConfig Service address");
         System.out.println(" --drconfiguser DrConfig Service username");
         System.out.println(" --ignorecerts Skip validation of certificates");
         System.out.println();
         System.out.println("Clear SRM server configuration");
         System.out.println();
         System.out.println("Usage: " + programName + " clear [options]");
         System.out.println();
         System.out.println("Options:");
         System.out.println(" --drconfigaddr DrConfig Service address");
         System.out.println(" --drconfiguser DrConfig Service username");
         System.out.println(" --ignorecerts Skip validation of certificates");
         System.out.println(" --pscuser PSC user");
   }
}
