content: package com.termux.shared.shell.command;
  
  import android.content.Intent;
  import android.net.Uri;
  
  import androidx.annotation.NonNull;
  import androidx.annotation.Nullable;
  
  import com.termux.shared.data.IntentUtils;
  import com.termux.shared.shell.command.result.ResultConfig;
  import com.termux.shared.shell.command.result.ResultData;
  import com.termux.shared.errors.Error;
  import com.termux.shared.logger.Logger;
  import com.termux.shared.markdown.MarkdownUtils;
  import com.termux.shared.data.DataUtils;
  import com.termux.shared.shell.command.runner.app.AppShell;
  import com.termux.terminal.TerminalSession;
  
  import java.util.Collections;
  import java.util.List;
  
  public class ExecutionCommand {
  
      /*
      The {@link ExecutionState#SUCCESS} and {@link ExecutionState#FAILED} is defined based on
      successful execution of command without any internal errors or exceptions being raised.
      The shell command {@link #exitCode} being non-zero **does not** mean that execution command failed.
      Only the {@link #errCode} being non-zero means that execution command failed from the Termux app
      perspective.
      */
  
      /** The {@link Enum} that defines {@link ExecutionCommand} state. */
      public enum ExecutionState {
  
          PRE_EXECUTION("Pre-Execution", 0),
          EXECUTING("Executing", 1),
          EXECUTED("Executed", 2),
          SUCCESS("Success", 3),
          FAILED("Failed", 4);
  
          private final String name;
          private final int value;
  
          ExecutionState(final String name, final int value) {
              this.name = name;
              this.value = value;
          }
  
          public String getName() {
              return name;
          }
  
          public int getValue() {
              return value;
          }
  
  
      }
  
      public enum Runner {
  
          /** Run command in {@link TerminalSession}. */
          TERMINAL_SESSION("terminal-session"),
  
          /** Run command in {@link AppShell}. */
          APP_SHELL("app-shell");
  
          ///** Run command in {@link AdbShell}. */
          //ADB_SHELL("adb-shell"),
  
          ///** Run command in {@link RootShell}. */
          //ROOT_SHELL("root-shell");
  
          private final String name;
  
          Runner(final String name) {
              this.name = name;
          }
  
          public String getName() {
              return name;
          }
  
          public boolean equalsRunner(String runner) {
              return runner != null && runner.equals(this.name);
          }
  
          /** Get {@link Runner} for {@code name} if found, otherwise {@code null}. */
          @Nullable
          public static Runner runnerOf(String name) {
              for (Runner v : Runner.values()) {
                  if (v.name.equals(name)) {
                      return v;
                  }
              }
              return null;
          }
  
          /** Get {@link Runner} for {@code name} if found, otherwise {@code def}. */
          @NonNull
          public static Runner runnerOf(@Nullable String name, @NonNull Runner def) {
              Runner runner = runnerOf(name);
              return runner != null ? runner : def;
          }
  
      }
  
      public enum ShellCreateMode {
  
          /** Always create {@link TerminalSession}. */
          ALWAYS("always"),
  
          /** Create shell only if no shell with {@link #shellName} found. */
          NO_SHELL_WITH_NAME("no-shell-with-name");
  
          private final String mode;
  
          ShellCreateMode(final String mode) {
              this.mode = mode;
          }
  
          public String getMode() {
              return mode;
          }
  
          public boolean equalsMode(String sessionCreateMode) {
              return sessionCreateMode != null && sessionCreateMode.equals(this.mode);
          }
  
          /** Get {@link ShellCreateMode} for {@code mode} if found, otherwise {@code null}. */
          @Nullable
          public static ShellCreateMode modeOf(String mode) {
              for (ShellCreateMode v : ShellCreateMode.values()) {
                  if (v.mode.equals(mode)) {
                      return v;
                  }
              }
              return null;
          }
  
      }
  
      /** The optional unique id for the {@link ExecutionCommand}. This should equal -1 if execution
       * command is not going to be managed by a shell manager. */
      public Integer id;
  
      /** The process id of command. */
      public int mPid = -1;
  
      /** The current state of the {@link ExecutionCommand}. */
      private ExecutionState currentState = ExecutionState.PRE_EXECUTION;
      /** The previous state of the {@link ExecutionCommand}. */
      private ExecutionState previousState = ExecutionState.PRE_EXECUTION;
  
  
      /** The executable for the {@link ExecutionCommand}. */
      public String executable;
      /** The executable Uri for the {@link ExecutionCommand}. */
      public Uri executableUri;
      /** The executable arguments array for the {@link ExecutionCommand}. */
      public String[] arguments;
      /** The stdin string for the {@link ExecutionCommand}. */
      public String stdin;
      /** The current working directory for the {@link ExecutionCommand}. */
      public String workingDirectory;
  
  
      /** The terminal transcript rows for the {@link ExecutionCommand}. */
      public Integer terminalTranscriptRows;
  
  
      /** The {@link Runner} for the {@link ExecutionCommand}. */
      public String runner;
  
      /** If the {@link ExecutionCommand} is meant to start a failsafe terminal session. */
      public boolean isFailsafe;
  
      /**
       * The {@link ExecutionCommand} custom log level for background {@link AppShell}
       * commands. By default, @link com.termux.shared.shell.StreamGobbler} only logs stdout and
       * stderr if {@link Logger} `CURRENT_LOG_LEVEL` is >= {@link Logger#LOG_LEVEL_VERBOSE} and
       * {@link AppShell} only logs stdin if `CURRENT_LOG_LEVEL` is >=
       * {@link Logger#LOG_LEVEL_DEBUG}.
       */
      public Integer backgroundCustomLogLevel;
  
  
      /** The session action of {@link Runner#TERMINAL_SESSION} commands. */
      public String sessionAction;
  
  
      /** The shell name of commands. */
      public String shellName;
  
      /** The {@link ShellCreateMode} of commands. */
      public String shellCreateMode;
  
      /** Whether to set {@link ExecutionCommand} shell environment. */
      public boolean setShellCommandShellEnvironment;
  
  
  
  
      /** The command label for the {@link ExecutionCommand}. */
      public String commandLabel;
      /** The markdown text for the command description for the {@link ExecutionCommand}. */
      public String commandDescription;
      /** The markdown text for the help of command for the {@link ExecutionCommand}. This can be used
       * to provide useful info to the user if an internal error is raised. */
      public String commandHelp;
  
  
      /** Defines the markdown text for the help of the Termux plugin API that was used to start the
       * {@link ExecutionCommand}. This can be used to provide useful info to the user if an internal
       * error is raised. */
      public String pluginAPIHelp;
  
  
      /** Defines the {@link Intent} received which started the command. */
      public Intent commandIntent;
  
      /** Defines if {@link ExecutionCommand} was started because of an external plugin request
       * like with an intent or from within Termux app itself. */
      public boolean isPluginExecutionCommand;
  
      /** Defines the {@link ResultConfig} for the {@link ExecutionCommand} containing information
       * on how to handle the result. */
      public final ResultConfig resultConfig = new ResultConfig();
  
      /** Defines the {@link ResultData} for the {@link ExecutionCommand} containing information
       * of the result. */
      public final ResultData resultData = new ResultData();
  
  
      /** Defines if processing results already called for this {@link ExecutionCommand}. */
      public boolean processingResultsAlreadyCalled;
  
      private static final String LOG_TAG = "ExecutionCommand";
  
  
      public ExecutionCommand() {
      }
  
      public ExecutionCommand(Integer id) {
          this.id = id;
      }
  
      public ExecutionCommand(Integer id, String executable, String[] arguments, String stdin, String workingDirectory, String runner, boolean isFailsafe) {
          this.id = id;
          this.executable = executable;
          this.arguments = arguments;
          this.stdin = stdin;
          this.workingDirectory = workingDirectory;
          this.runner = runner;
          this.isFailsafe = isFailsafe;
      }
  
  
      public boolean isPluginExecutionCommandWithPendingResult() {
          return isPluginExecutionCommand && resultConfig.isCommandWithPendingResult();
      }
  
  
      public synchronized boolean setState(ExecutionState newState) {
          // The state transition cannot go back or change if already at {@link ExecutionState#SUCCESS}
          if (newState.getValue() < currentState.getValue() || currentState == ExecutionState.SUCCESS) {
              Logger.logError(LOG_TAG, "Invalid "+ getCommandIdAndLabelLogString() + " state transition from \"" + currentState.getName() + "\" to " +  "\"" + newState.getName() + "\"");
              return false;
          }
  
          // The {@link ExecutionState#FAILED} can be set again, like to add more errors, but we don't update
          // {@link #previousState} with the {@link #currentState} value if its at {@link ExecutionState#FAILED} to
          // preserve the last valid state
          if (currentState != ExecutionState.FAILED)
              previousState = currentState;
  
          currentState = newState;
          return  true;
      }
  
      public synchronized boolean hasExecuted() {
          return currentState.getValue() >= ExecutionState.EXECUTED.getValue();
      }
  
      public synchronized boolean isExecuting() {
          return currentState == ExecutionState.EXECUTING;
      }
  
      public synchronized boolean isSuccessful() {
          return currentState == ExecutionState.SUCCESS;
      }
  
  
      public synchronized boolean setStateFailed(@NonNull Error error) {
          return setStateFailed(error.getType(), error.getCode(), error.getMessage(), null);
      }
  
      public synchronized boolean setStateFailed(@NonNull Error error, Throwable throwable) {
          return setStateFailed(error.getType(), error.getCode(), error.getMessage(), Collections.singletonList(throwable));
      }
      public synchronized boolean setStateFailed(@NonNull Error error, List<Throwable> throwablesList) {
          return setStateFailed(error.getType(), error.getCode(), error.getMessage(), throwablesList);
      }
  
      public synchronized boolean setStateFailed(int code, String message) {
          return setStateFailed(null, code, message, null);
      }
  
      public synchronized boolean setStateFailed(int code, String message, Throwable throwable) {
          return setStateFailed(null, code, message, Collections.singletonList(throwable));
      }
  
      public synchronized boolean setStateFailed(int code, String message, List<Throwable> throwablesList) {
          return setStateFailed(null, code, message, throwablesList);
      }
      public synchronized boolean setStateFailed(String type, int code, String message, List<Throwable> throwablesList) {
          if (!this.resultData.setStateFailed(type, code, message, throwablesList)) {
              Logger.logWarn(LOG_TAG, "setStateFailed for "  + getCommandIdAndLabelLogString() + " resultData encountered an error.");
          }
  
          return setState(ExecutionState.FAILED);
      }
  
      public synchronized boolean shouldNotProcessResults() {
          if (processingResultsAlreadyCalled) {
              return true;
          } else {
              processingResultsAlreadyCalled = true;
              return false;
          }
      }
  
      public synchronized boolean isStateFailed() {
          if (currentState != ExecutionState.FAILED)
              return false;
  
          if (!resultData.isStateFailed()) {
              Logger.logWarn(LOG_TAG, "The "  + getCommandIdAndLabelLogString() + " has an invalid errCode value set in errors list while having ExecutionState.FAILED state.\n" + resultData.errorsList);
              return false;
          } else {
              return true;
          }
      }
  
  
      @NonNull
      @Override
      public String toString() {
          if (!hasExecuted())
              return getExecutionInputLogString(this, true, true);
          else {
              return getExecutionOutputLogString(this, true, true, true);
          }
      }
  
      /**
       * Get a log friendly {@link String} for {@link ExecutionCommand} execution input parameters.
       *
       * @param executionCommand The {@link ExecutionCommand} to convert.
       * @param ignoreNull Set to {@code true} if non-critical {@code null} values are to be ignored.
       * @param logStdin Set to {@code true} if {@link #stdin} should be logged.
       * @return Returns the log friendly {@link String}.
       */
      public static String getExecutionInputLogString(final ExecutionCommand executionCommand, boolean ignoreNull, boolean logStdin) {
          if (executionCommand == null) return "null";
  
          StringBuilder logString = new StringBuilder();
  
          logString.append(executionCommand.getCommandIdAndLabelLogString()).append(":");
  
          if (executionCommand.mPid != -1)
              logString.append("\n").append(executionCommand.getPidLogString());
  
          if (executionCommand.previousState != ExecutionState.PRE_EXECUTION)
              logString.append("\n").append(executionCommand.getPreviousStateLogString());
          logString.append("\n").append(executionCommand.getCurrentStateLogString());
  
          logString.append("\n").append(executionCommand.getExecutableLogString());
          logString.append("\n").append(executionCommand.getArgumentsLogString());
          logString.append("\n").append(executionCommand.getWorkingDirectoryLogString());
          logString.append("\n").append(executionCommand.getRunnerLogString());
          logString.append("\n").append(executionCommand.getIsFailsafeLogString());
  
          if (Runner.APP_SHELL.equalsRunner(executionCommand.runner)) {
              if (logStdin && (!ignoreNull || !DataUtils.isNullOrEmpty(executionCommand.stdin)))
                  logString.append("\n").append(executionCommand.getStdinLogString());
  
              if (!ignoreNull || executionCommand.backgroundCustomLogLevel != null)
                  logString.append("\n").append(executionCommand.getBackgroundCustomLogLevelLogString());
          }
  
          if (!ignoreNull || executionCommand.sessionAction != null)
              logString.append("\n").append(executionCommand.getSessionActionLogString());
  
          if (!ignoreNull || executionCommand.shellName != null) {
              logString.append("\n").append(executionCommand.getShellNameLogString());
          }
  
          if (!ignoreNull || executionCommand.shellCreateMode != null) {
              logString.append("\n").append(executionCommand.getShellCreateModeLogString());
          }
  
          logString.append("\n").append(executionCommand.getSetRunnerShellEnvironmentLogString());
  
          if (!ignoreNull || executionCommand.commandIntent != null)
              logString.append("\n").append(executionCommand.getCommandIntentLogString());
  
          logString.append("\n").append(executionCommand.getIsPluginExecutionCommandLogString());
          if (executionCommand.isPluginExecutionCommand)
              logString.append("\n").append(ResultConfig.getResultConfigLogString(executionCommand.resultConfig, ignoreNull));
  
          return logString.toString();
      }
  
      /**
       * Get a log friendly {@link String} for {@link ExecutionCommand} execution output parameters.
       *
       * @param executionCommand The {@link ExecutionCommand} to convert.
       * @param ignoreNull Set to {@code true} if non-critical {@code null} values are to be ignored.
       * @param logResultData Set to {@code true} if {@link #resultData} should be logged.
       * @param logStdoutAndStderr Set to {@code true} if {@link ResultData#stdout} and {@link ResultData#stderr} should be logged.
       * @return Returns the log friendly {@link String}.
       */
      public static String getExecutionOutputLogString(final ExecutionCommand executionCommand, boolean ignoreNull, boolean logResultData, boolean logStdoutAndStderr) {
          if (executionCommand == null) return "null";
  
          StringBuilder logString = new StringBuilder();
  
          logString.append(executionCommand.getCommandIdAndLabelLogString()).append(":");
  
          logString.append("\n").append(executionCommand.getPreviousStateLogString());
          logString.append("\n").append(executionCommand.getCurrentStateLogString());
  
          if (logResultData)
              logString.append("\n").append(ResultData.getResultDataLogString(executionCommand.resultData, logStdoutAndStderr));
  
          return logString.toString();
      }
  
      /**
       * Get a log friendly {@link String} for {@link ExecutionCommand} with more details.
       *
       * @param executionCommand The {@link ExecutionCommand} to convert.
       * @return Returns the log friendly {@link String}.
       */
      public static String getDetailedLogString(final ExecutionCommand executionCommand) {
          if (executionCommand == null) return "null";
  
          StringBuilder logString = new StringBuilder();
  
          logString.append(getExecutionInputLogString(executionCommand, false, true));
          logString.append(getExecutionOutputLogString(executionCommand, false, true, true));
  
          logString.append("\n").append(executionCommand.getCommandDescriptionLogString());
          logString.append("\n").append(executionCommand.getCommandHelpLogString());
          logString.append("\n").append(executionCommand.getPluginAPIHelpLogString());
  
          return logString.toString();
      }
  
      /**
       * Get a markdown {@link String} for {@link ExecutionCommand}.
       *
       * @param executionCommand The {@link ExecutionCommand} to convert.
       * @return Returns the markdown {@link String}.
       */
      public static String getExecutionCommandMarkdownString(final ExecutionCommand executionCommand) {
          if (executionCommand == null) return "null";
  
          if (executionCommand.commandLabel == null) executionCommand.commandLabel = "Execution Command";
  
          StringBuilder markdownString = new StringBuilder();
  
          markdownString.append("## ").append(executionCommand.commandLabel).append("\n");
  
          if (executionCommand.mPid != -1)
              markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Pid", executionCommand.mPid, "-"));
  
          markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Previous State", executionCommand.previousState.getName(), "-"));
          markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Current State", executionCommand.currentState.getName(), "-"));
  
          markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Executable", executionCommand.executable, "-"));
          markdownString.append("\n").append(getArgumentsMarkdownString("Arguments", executionCommand.arguments));
          markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Working Directory", executionCommand.workingDirectory, "-"));
          markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Runner", executionCommand.runner, "-"));
          markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("isFailsafe", executionCommand.isFailsafe, "-"));
  
          if (Runner.APP_SHELL.equalsRunner(executionCommand.runner)) {
              if (!DataUtils.isNullOrEmpty(executionCommand.stdin))
                  markdownString.append("\n").append(MarkdownUtils.getMultiLineMarkdownStringEntry("Stdin", executionCommand.stdin, "-"));
              if (executionCommand.backgroundCustomLogLevel != null)
                  markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Background Custom Log Level", executionCommand.backgroundCustomLogLevel, "-"));
          }
  
          markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Session Action", executionCommand.sessionAction, "-"));
  
          markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Shell Name", executionCommand.shellName, "-"));
          markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Shell Create Mode", executionCommand.shellCreateMode, "-"));
          markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Set Shell Command Shell Environment", executionCommand.setShellCommandShellEnvironment, "-"));
  
          markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("isPluginExecutionCommand", executionCommand.isPluginExecutionCommand, "-"));
  
          markdownString.append("\n\n").append(ResultConfig.getResultConfigMarkdownString(executionCommand.resultConfig));
  
          markdownString.append("\n\n").append(ResultData.getResultDataMarkdownString(executionCommand.resultData));
  
          if (executionCommand.commandDescription != null || executionCommand.commandHelp != null) {
              if (executionCommand.commandDescription != null)
                  markdownString.append("\n\n### Command Description\n\n").append(executionCommand.commandDescription).append("\n");
              if (executionCommand.commandHelp != null)
                  markdownString.append("\n\n### Command Help\n\n").append(executionCommand.commandHelp).append("\n");
              markdownString.append("\n##\n");
          }
  
          if (executionCommand.pluginAPIHelp != null) {
              markdownString.append("\n\n### Plugin API Help\n\n").append(executionCommand.pluginAPIHelp);
              markdownString.append("\n##\n");
          }
  
          return markdownString.toString();
      }
  
  
      public String getIdLogString() {
          if (id != null)
              return "(" + id + ") ";
          else
              return "";
      }
  
      public String getPidLogString() {
          return "Pid: `" + mPid + "`";
      }
  
      public String getCurrentStateLogString() {
          return "Current State: `" + currentState.getName() + "`";
      }
  
      public String getPreviousStateLogString() {
          return "Previous State: `" + previousState.getName() + "`";
      }
  
      public String getCommandLabelLogString() {
          if (commandLabel != null && !commandLabel.isEmpty())
              return commandLabel;
          else
              return "Execution Command";
      }
  
      public String getCommandIdAndLabelLogString() {
          return getIdLogString() + getCommandLabelLogString();
      }
  
      public String getExecutableLogString() {
          return "Executable: `" + executable + "`";
      }
  
      public String getArgumentsLogString() {
          return getArgumentsLogString("Arguments", arguments);
      }
  
      public String getWorkingDirectoryLogString() {
          return "Working Directory: `" + workingDirectory + "`";
      }
  
      public String getRunnerLogString() {
          return Logger.getSingleLineLogStringEntry("Runner", runner, "-");
      }
  
      public String getIsFailsafeLogString() {
          return "isFailsafe: `" + isFailsafe + "`";
      }
  
      public String getStdinLogString() {
          if (DataUtils.isNullOrEmpty(stdin))
              return "Stdin: -";
          else
              return Logger.getMultiLineLogStringEntry("Stdin", stdin, "-");
      }
  
      public String getBackgroundCustomLogLevelLogString() {
          return "Background Custom Log Level: `" + backgroundCustomLogLevel + "`";
      }
  
      public String getSessionActionLogString() {
          return Logger.getSingleLineLogStringEntry("Session Action", sessionAction, "-");
      }
  
      public String getShellNameLogString() {
          return Logger.getSingleLineLogStringEntry("Shell Name", shellName, "-");
      }
  
      public String getShellCreateModeLogString() {
          return Logger.getSingleLineLogStringEntry("Shell Create Mode", shellCreateMode, "-");
      }
  
      public String getSetRunnerShellEnvironmentLogString() {
          return "Set Shell Command Shell Environment: `" + setShellCommandShellEnvironment + "`";
      }
  
      public String getCommandDescriptionLogString() {
          return Logger.getSingleLineLogStringEntry("Command Description", commandDescription, "-");
      }
  
      public String getCommandHelpLogString() {
          return Logger.getSingleLineLogStringEntry("Command Help", commandHelp, "-");
      }
  
      public String getPluginAPIHelpLogString() {
          return Logger.getSingleLineLogStringEntry("Plugin API Help", pluginAPIHelp, "-");
      }
  
      public String getCommandIntentLogString() {
          if (commandIntent == null)
              return "Command Intent: -";
          else
              return Logger.getMultiLineLogStringEntry("Command Intent", IntentUtils.getIntentString(commandIntent), "-");
      }
  
      public String getIsPluginExecutionCommandLogString() {
          return "isPluginExecutionCommand: `" + isPluginExecutionCommand + "`";
      }
  
  
      /**
       * Get a log friendly {@link String} for {@link List<String>} argumentsArray.
       * If argumentsArray are null or of size 0, then `Arguments: -` is returned. Otherwise
       * following format is returned:
       *
       * Arguments:
       * ```
       * Arg 1: `value`
       * Arg 2: 'value`
       * ```
       *
       * @param argumentsArray The {@link String[]} argumentsArray to convert.
       * @return Returns the log friendly {@link String}.
       */
      public static String getArgumentsLogString(String label, final String[] argumentsArray) {
          StringBuilder argumentsString = new StringBuilder(label + ":");
  
          if (argumentsArray != null && argumentsArray.length != 0) {
              argumentsString.append("\n```\n");
              for (int i = 0; i != argumentsArray.length; i++) {
                  argumentsString.append(Logger.getSingleLineLogStringEntry("Arg " + (i + 1),
                      DataUtils.getTruncatedCommandOutput(argumentsArray[i], Logger.LOGGER_ENTRY_MAX_SAFE_PAYLOAD / 5, true, false, true),
                      "-")).append("\n");
              }
              argumentsString.append("```");
          } else{
              argumentsString.append(" -");
          }
  
          return argumentsString.toString();
      }
  
      /**
       * Get a markdown {@link String} for {@link String[]} argumentsArray.
       * If argumentsArray are null or of size 0, then `**Arguments:** -` is returned. Otherwise
       * following format is returned:
       *
       * **Arguments:**
       *
       * **Arg 1:**
       * ```
       * value
       * ```
       * **Arg 2:**
       * ```
       * value
       *```
       *
       * @param argumentsArray The {@link String[]} argumentsArray to convert.
       * @return Returns the markdown {@link String}.
       */
      public static String getArgumentsMarkdownString(String label, final String[] argumentsArray) {
          StringBuilder argumentsString = new StringBuilder("**" + label + ":**");
  
          if (argumentsArray != null && argumentsArray.length != 0) {
              argumentsString.append("\n");
              for (int i = 0; i != argumentsArray.length; i++) {
                  argumentsString.append(MarkdownUtils.getMultiLineMarkdownStringEntry("Arg " + (i + 1), argumentsArray[i], "-")).append("\n");
              }
          } else{
              argumentsString.append(" -  ");
          }
  
          return argumentsString.toString();
      }
  
  }
  