content: package fr.mmarie.core;
  
  import com.google.common.base.Preconditions;
  import com.google.common.base.Strings;
  import com.google.common.collect.ArrayListMultimap;
  import com.google.common.collect.Multimap;
  import com.google.inject.Inject;
  import fr.mmarie.api.gitlab.Commit;
  import fr.mmarie.api.gitlab.Event;
  import fr.mmarie.api.gitlab.User;
  import fr.mmarie.api.jira.Comment;
  import fr.mmarie.core.gitlab.GitLabService;
  import fr.mmarie.core.jira.JiraService;
  import lombok.extern.slf4j.Slf4j;
  import retrofit.Response;
  
  import java.io.IOException;
  import java.text.DateFormat;
  import java.text.SimpleDateFormat;
  import java.util.Collection;
  import java.util.Date;
  
  @Slf4j
  public class IntegrationService {
      public static final DateFormat DATE_FORMAT = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss");
  
      private final GitLabService gitLabService;
      private final JiraService jiraService;
  
      @Inject
      public IntegrationService(GitLabService gitLabService, JiraService jiraService) {
          this.gitLabService = gitLabService;
          this.jiraService = jiraService;
      }
  
      public String getDateAsString(Date date) {
          if (date == null) {
              return "unknown date of commit";
          } else {
              return DATE_FORMAT.format(date);
          }
      }
  
      public String buildComment(User user, String repositoryName, Commit commit) {
          if(Strings.isNullOrEmpty(user.getUsername())) {
              return String.format("%s mentioned this issue in [a commit of %s|%s] \r\n "
                              + "*%s* : %s",
                      user.getName(), repositoryName, commit.getUrl(),
                      getDateAsString(commit.getTimestamp()), commit.getMessage());
          } else {
              return String.format("[%s|%s] mentioned this issue in [a commit of %s|%s] \r\n"
                              + "*%s* : %s",
                      user.getName(), gitLabService.getUserUrl(user.getUsername()), repositoryName, commit.getUrl(),
                      getDateAsString(commit.getTimestamp()), commit.getMessage());
          }
      }
  
      public String buildCommentForTransition(User user, String repositoryName, Commit commit) {
          if(Strings.isNullOrEmpty(user.getUsername())) {
              return String.format("%s changed status of this issue in [a commit of %s|%s] to *%s* \r\n\r\n "
                              + "*%s* : %s",
                      user.getName(), repositoryName, commit.getUrl(),
                      JiraService.TRANSITION_HOLDER,
                      getDateAsString(commit.getTimestamp()), commit.getMessage());
          } else {
              return String.format("[%s|%s] changed status of this issue in [a commit of %s|%s] to *%s* \r\n\r\n"
                              + "*%s* : %s",
                      user.getName(), gitLabService.getUserUrl(user.getUsername()), repositoryName, commit.getUrl(),
                      JiraService.TRANSITION_HOLDER,
                      getDateAsString(commit.getTimestamp()), commit.getMessage());
          }
      }
  
      public void commentIssue(String repositoryName, User user, Collection<Commit> commits, String issue) {
          if(jiraService.isExistingIssue(issue)) {
              commits.forEach(commit -> {
                  if(!jiraService.isIssueAlreadyCommented(issue, commit.getId())) {
                      try {
                          log.info("Comment issue <{}> for commit <{}>", issue, commit);
                          if(!jiraService.performTransition(commit.getMessage(), issue,
                                  buildCommentForTransition(user,
                                          repositoryName,
                                          commit))) {
                              jiraService.commentIssue(issue,
                                      new Comment(buildComment(user,
                                              repositoryName,
                                              commit)));
                          }
                      } catch (IOException e) {
                          log.error("Unable to comment issue <{}>", issue, e);
                      }
                  } else {
                      log.warn("Issue <{}> has already been commented for commit <{}>",
                              issue,
                              commit.getId());
                  }
              });
          } else {
              log.warn("Issue <{}> has been mentioned, but does not exists", issue);
          }
      }
  
      public void performPushEvent(Event event) {
          Preconditions.checkNotNull(event.getCommits(), "commits array can not be null");
          // For each commit, extract jira issues
          Multimap<String, Commit> jiraIssues = ArrayListMultimap.create();
          event.getCommits().forEach(commit ->
                  jiraService.extractIssuesFromMessage(commit.getMessage())
                          .forEach(issue -> jiraIssues.put(issue, commit)));
  
          if(jiraIssues.size() > 0) {
              User user = getUser(event);
  
              jiraIssues.asMap().forEach((issue, commits) -> commentIssue(event.getRepository().getName(), user, commits, issue));
          }
      }
  
      public User getUser(Event event) {
          try {
              Response<User> userResponse = gitLabService.getUser(event.getUserId());
              Preconditions.checkArgument(userResponse.code() == 200);
  
              return userResponse.body();
          } catch (Exception e) {
              log.error("Unable to get gitlab user with id <{}>, comment issue with pusher username <{}>",
                      event.getUserId(),
                      event.getUserName());
              return new User(event.getUserId(), null, event.getUserName());
          }
      }
  }
  