/* ****************************************************************************
 * Copyright 2013-2014 VMware, Inc.  All rights reserved.
 * ***************************************************************************/

package com.vmware.samples.recovery;

import java.util.List;

import com.vmware.samples.srm.ApplicationException;
import com.vmware.samples.srm.SrmConnectionUtil;

import com.vmware.srm.NotAuthenticatedFaultMsg;
import com.vmware.srm.RuntimeFaultFaultMsg;
import com.vmware.srm.SrmPortType;
import com.vmware.srm.SrmRecoveryPlanInfo;
import com.vmware.srm.SrmServiceInstanceContent;
import com.vmware.vim25.ManagedObjectReference;


/**
 * Provides a sample application that obtains the list of SRM recovery plans,
 * and (optionally) prints details about a specific recovery plan.
 */
public final class RecoveryPlanList {

   /**
    * Entry point into this sample application.
    * @param args the list of command-line arguments.
    */
   public static void main(final String[] args) {

      final String  progName = RecoveryPlanList.class.getSimpleName();
      final Options options;
      try {
         options = Options.parseOptions(args);
      } catch (final Options.ShowHelpThrowable t) {
         Options.printHelp(progName);
         return;
      } catch (final Options.InvalidCliArgumentException icae) {
         System.err.println(progName + ": " + icae.getMessage());
         Options.printHelp(progName);
         System.exit(1);
         return; // Not reached...
      }

      if (options._ignoreCert) {
         SrmConnectionUtil.ignoreSslCert();
      }

      try {
         int found = 0;

         System.out.println("Searching for recovery plans.");
         found += RecoveryPlanList.doListPlans(options);
         System.out.println(
            "Finished searching for recovery plans (found " + found + ").");
      } catch (final ApplicationException e) {
         System.err.println(progName + ": " + e.getMessage());
         e.printStackTrace();
         System.exit(1);
      }
   }

   /**
    * Retrieve a list of SRM's recovery plans, and (optionally) find details
    * about a specific plan.
    *
    * @param options The command-line options that configure the execution of
    *    the sample application.
    * @return The number of recovery plans encountered.
    * @throws ApplicationException if there is a fatal error in the execution of
    *    the application.  This exception should have all the information a user
    *    needs to diagnose the problem in {@code getMessage()}.
    */
   public static int doListPlans(final Options options)
      throws ApplicationException {

      System.out.println("Connecting to " + options._url);

      // This SRM port instance is our communication layer, through which we
      // make our remote API calls.
      final SrmPortType srmPort = SrmConnectionUtil.openSrmPort(
         options._url, options._userName, options._password);

      try {
         // Get the ServiceInstanceContent as it is our handle to the other SRM
         // subsystems.  In this case, we're interested in the Recovery
         // interfaces.
         final SrmServiceInstanceContent sic =
            SrmConnectionUtil.findSrmServiceInstanceContent(srmPort);

         final List<ManagedObjectReference> plans =
            RecoveryPlanList.findPlanList(srmPort, sic);
         if (plans == null) {
            return 0;
         }

         for (final ManagedObjectReference plan : plans) {

            final SrmRecoveryPlanInfo info;
            try {
               info = srmPort.recoveryPlanGetInfo(plan);
            } catch (final RuntimeFaultFaultMsg e) {
               // If we can't find a single plan's information, try to continue.
               System.err.println(
                  "Cannot retrieve SRM recovery plan information" +
                  e.getMessage());
               continue;
            }

            System.out.println("RecoveryPlan : " + info.getName());

            if ((options._planName == null) ||
                (info.getName().equals(options._planName))) {
               System.out.println("  RecoveryPlan state : " + info.getState());
            }
         }

         return plans.size();
      } finally {
         try {
            srmPort.srmLogoutLocale(SrmConnectionUtil._serviceInstanceRef);
         } catch (final NotAuthenticatedFaultMsg e) {
            // Not important enough to inform user at this time.
         } catch (final RuntimeFaultFaultMsg e) {
            System.err.println(
               "Warning -- unable to log out of SRM: " + e.getMessage());
         }
      }
   }

   /**
    * Finds all the (references to the) SRM recovery plans.
    *
    * @param srmPort An open connection to SRM.
    * @param sic     SRM's ServiceInstanceContent information holds the location
    *    of the recovery interface.
    *
    * @return An array of references to managed objects that represent SRM
    *    recovery plans.
    *
    * @throws ApplicationException There was an error acquiring the list of
    *    recovery plans.
    */
   private static List<ManagedObjectReference> findPlanList(
      final SrmPortType srmPort, final SrmServiceInstanceContent sic)
      throws ApplicationException {

      final ManagedObjectReference recoveryRef = sic.getRecovery();

      try {
         return srmPort.listPlans(recoveryRef);
      } catch (final RuntimeFaultFaultMsg e) {
         throw new ApplicationException(
            "Cannot retrieve SRM recovery plan list", e);
      }
   }

   /**
    * This class defines a library of functions.  So far there is no need for an
    * instance, so we will hide the CTOR.
    */
   private RecoveryPlanList() {
      // Does nothing.
   }
}
