/* Exposed methods */

        /// <summary>
        /// Get WCSCLI user commands, translate them to corresponding CM REST API calls
        /// (via the command class), prints CM Response output
        /// Figure out if this is a local machine command or a CM service command
        /// Prompt for CM service credentials to talk to the CM if required
        /// Uses ConnectionManager class to establish WCF connection
        /// </summary>
        /// <param name="inputString"></param>
        internal static void InteractiveParseUserCommandGetCmResponse(bool isSerialClient, string inputString)
        {
            char[]   cmdDelimiters  = { ' ' };
            string[] inputSubString = null;
            command  mappedCommand  = null;

            try
            {
                string inputStringLower = inputString.ToLower();

                // Check if it is SetChassisManagerAssetInfo or SetPDBAssetInfo or SetBladeAssetInfo command
                if ((inputStringLower.Contains(WcsCliConstants.setCMAssetInfo) || inputStringLower.Contains(WcsCliConstants.setPDBAssetInfo) || inputStringLower.Contains(WcsCliConstants.setBladeAssetInfo)) &&
                    inputStringLower.Contains("-p"))
                {
                    // Parse the payload for set asset commands
                    inputSubString = ParseSetAssetInfo(inputString);
                }
                else
                {
                    // Get all individual user-entered arguments as separate strings
                    // StringSplitOptions.RemoveEmptyEntries removes extra spaces
                    inputSubString = inputString.Split(cmdDelimiters, StringSplitOptions.RemoveEmptyEntries);
                }

                // Prevents parsing more than maxArgCount arguments - DOS attack scenario
                if (inputSubString.Length > command.maxArgCount)
                {
                    Console.Write(WcsCliConstants.consoleString + " " + WcsCliConstants.invalidCommandString);
                    return;
                }

                // Command string should have at least two argument strings
                if (inputSubString.Length <= 1)
                {
                    if (inputSubString.Length == 0)
                    {
                        return;
                    }
                    Console.WriteLine(WcsCliConstants.invalidCommandString);
                    return;
                }

                // The command string should start with "WcsCli"
                if (!inputSubString[0].Equals(WcsCliConstants.WcsCli, StringComparison.InvariantCultureIgnoreCase))
                {
                    Console.WriteLine(WcsCliConstants.invalidCommandString);
                    return;
                }

                // The first argument which is the command name length must be smaller than indicated by command.maxArgLength
                if (inputSubString[1].Length > command.maxArgLength || inputSubString[1][0] != WcsCliConstants.argIndicatorVar)
                {
                    Console.WriteLine(WcsCliConstants.invalidCommandString);
                    return;
                }

                // Map the user-entered command name to the corresponding command object created by CommandInitializer() function
                mappedCommand = new command();
                if (commandMap.TryGetValue(inputSubString[1].Remove(0, 1), out mappedCommand) != true)
                {
                    // Handle unknown command
                    Console.WriteLine(WcsCliConstants.invalidCommandString);
                    return;
                }
                mappedCommand.isSerialClient = isSerialClient;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return;
            }

            try
            {
                // (re)Allocate argVal for the mappedCommand - it has to get a new space for each time command is executed
                mappedCommand.argVal = new Dictionary <char, dynamic>();

                // Execute the commandImplementation() function corresponding to the command entered by the user
                // Command is executed only when the argument syntax is correct as checked by isArgSyntaxCorrect()
                // IsArgSyntaxCorrect() also extracts the argument indicator and value and adds them into mappedCommand.argVal
                if (IsArgSyntaxCorrect(mappedCommand, inputSubString))
                {
                    if (mappedCommand.argVal.ContainsKey('h'))
                    {
                        // If the command is establishCmConnection and it is a console client.. do not display help.. since the h option is used for hostname in the console..
                        if (!(mappedCommand.name.Equals(WcsCliConstants.establishCmConnection, StringComparison.InvariantCultureIgnoreCase) &&
                              isSerialClient == false))
                        {
                            Console.WriteLine(mappedCommand.helpString);
                        }
                    }
                    else
                    {
                        // If this is a CM command, check if a connection has already been established, otherwise prompt for connection
                        if (mappedCommand.isCmServiceCommand)
                        {
                            if (!WcsCli2CmConnectionManager.IsCmServiceConnectionActive)
                            {
                                Console.WriteLine("Please connect to CM service using the \"{0}\" command and try again.", WcsCliConstants.establishCmConnection);
                                Console.WriteLine(WcsCliConstants.establishCmConnectionHelp);
                                return;
                            }
                        }

                        if (AreAllArgsPresent(mappedCommand))
                        {
                            // Execute the command
                            mappedCommand.commandImplementation();

                            // Let us allow batch only for the internal gethostportssloption command to avoid unintentional/intentional recursion
                            if (mappedCommand.name.Equals(WcsCliConstants.establishCmConnection, StringComparison.InvariantCultureIgnoreCase))
                            {
                                // If the command has a batch parameter - process the commands in the batch file
                                if (mappedCommand.argVal.ContainsKey('b'))
                                {
                                    if (isSerialClient)
                                    {
                                        Console.WriteLine("The batch -b option is not supported in serial mode..");
                                        return;
                                    }
                                    dynamic batchFile = null;
                                    if (mappedCommand.argVal.TryGetValue('b', out batchFile))
                                    {
                                        uint     batchInputFileLinesIndex = 0;
                                        string[] batchInputFileLines      = System.IO.File.ReadAllLines((string)batchFile);
                                        while (batchInputFileLinesIndex < batchInputFileLines.Length)
                                        {
                                            try
                                            {
                                                // Read one command at a time
                                                inputString = batchInputFileLines[batchInputFileLinesIndex];
                                                batchInputFileLinesIndex++;
                                                if (inputString == null)
                                                {
                                                    continue;
                                                }

                                                // Recursive call for executing command in the batch file
                                                InteractiveParseUserCommandGetCmResponse(isSerialClient, inputString);
                                            }
                                            catch (Exception)
                                            {
                                                // skip this entry in the batch file
                                                Console.WriteLine("Error in parsing batch file. Skipped entries");
                                            }
                                        }
                                    }
                                    else
                                    {
                                        Console.WriteLine("Error in getting batch file name.");
                                    }
                                }
                            }
                        }
                        else
                        {
                            // If the command is establishCmConnection and it is a console client.. do not display help.. since the h option is used for hostname in the console..
                            if (!(mappedCommand.name.Equals(WcsCliConstants.establishCmConnection, StringComparison.InvariantCultureIgnoreCase) &&
                                  isSerialClient == false))
                            {
                                Console.WriteLine(WcsCliConstants.argsMissingString);
                                Console.WriteLine(mappedCommand.helpString);
                            }
                            else if (isSerialClient == false)
                            {
                                // Even for establishCmconnection command we need to display args missing message,
                                // since 'h' option is used for hostname in console as mentioned above so not displaying comamnd help.
                                Console.WriteLine(WcsCliConstants.argsMissingString);
                            }
                        }
                    }
                }
                else
                {
                    // If the command is establishCmConnection and it is a console client.. do not display help.. since the h option is used for hostname in the console..
                    if (!(mappedCommand.name.Equals(WcsCliConstants.establishCmConnection, StringComparison.InvariantCultureIgnoreCase) &&
                          isSerialClient == false))
                    {
                        Console.WriteLine(WcsCliConstants.argsSyntaxIncorrect);
                        Console.WriteLine(mappedCommand.helpString);
                    }
                    else if (isSerialClient == false)
                    {
                        // Even for establishCmconnection command we need to display args missing message,
                        // since 'h' option is used for hostname in console as mentioned above so not displaying comamnd help.
                        Console.WriteLine(WcsCliConstants.argsSyntaxIncorrect);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(WcsCliConstants.unknownError + ex.Message);
            }
        }