/**
   * Create pull request on a background thread
   *
   * <p>This method will first check to see if the local branch has a tracking branch: yes: push the
   * commits to the remote tracking branch no: try create a remote branch matching the local branch
   * name exactly, with the remote set to the GitRemote of the target branch
   *
   * <p>If push fails for whatever reason, stop and show an error message
   *
   * <p>After we push the local branch, then create the pull request. Pull request link should be
   * returned in a notification bubble
   */
  public void createPullRequest() {
    /* verifying branch selections */
    final GitLocalBranch sourceBranch = this.getSourceBranch();
    final GitRemoteBranch targetBranch = this.getTargetBranch();

    if (sourceBranch == null) {
      // how did we get here? validation failed?
      notifyCreateFailedError(
          project, TfPluginBundle.message(TfPluginBundle.KEY_CREATE_PR_ERRORS_SOURCE_EMPTY));
      return;
    }

    if (targetBranch == null) {
      // how did we get here? validation failed?
      notifyCreateFailedError(
          project, TfPluginBundle.message(TfPluginBundle.KEY_CREATE_PR_ERRORS_TARGET_NOT_SELECTED));
      return;
    }

    if (targetBranch.equals(this.getRemoteTrackingBranch())) {
      // how did we get here? Didn't we filter you out?
      notifyCreateFailedError(
          project,
          TfPluginBundle.message(TfPluginBundle.KEY_CREATE_PR_ERRORS_TARGET_IS_LOCAL_TRACKING));
      return;
    }

    // TODO Determine the correct/best way to get the remote url
    final String gitRemoteUrl = TfGitHelper.getTfGitRemote(gitRepository).getFirstUrl();
    final CreatePullRequestModel createModel = this;
    /* Let's keep all server interactions to a background thread */
    final Task.Backgroundable createPullRequestTask =
        new Task.Backgroundable(
            project,
            TfPluginBundle.message(TfPluginBundle.KEY_CREATE_PR_DIALOG_TITLE),
            true,
            PerformInBackgroundOption.DEAF) {
          @Override
          public void run(@NotNull ProgressIndicator progressIndicator) {
            // get context from manager, create PAT if needed, and store in active context
            final ServerContext context =
                ServerContextManager.getInstance()
                    .getAuthenticatedContext(
                        gitRemoteUrl,
                        TfPluginBundle.message(TfPluginBundle.KEY_PAT_TOKEN_DESC),
                        true);

            if (context == null) {
              notifyCreateFailedError(
                  project,
                  TfPluginBundle.message(
                      TfPluginBundle.KEY_ERRORS_AUTH_NOT_SUCCESSFUL, gitRemoteUrl));
              return;
            }

            ListenableFuture<Pair<String, GitCommandResult>> pushResult =
                doPushCommits(
                    gitRepository, sourceBranch, targetBranch.getRemote(), progressIndicator);

            Futures.addCallback(
                pushResult,
                new FutureCallback<Pair<String, GitCommandResult>>() {
                  @Override
                  public void onSuccess(@Nullable Pair<String, GitCommandResult> result) {
                    if (result != null && StringUtils.isNotEmpty(result.getFirst())) {
                      final String title = createModel.getTitle();
                      final String description = createModel.getDescription();
                      final String branchNameOnRemoteServer = result.getFirst();

                      doCreatePullRequest(
                          project,
                          context,
                          title,
                          description,
                          branchNameOnRemoteServer,
                          targetBranch);
                    } else {
                      // I really don't have anything else to say, push failed, the title says it
                      // all
                      // I have no error message to be more specific
                      notifyPushFailedError(createModel.getProject(), StringUtils.EMPTY);
                    }
                  }

                  @Override
                  public void onFailure(Throwable t) {
                    notifyPushFailedError(createModel.getProject(), t.getLocalizedMessage());
                  }
                });
          }
        };

    createPullRequestTask.queue();
  }