<commit_before>package com.box.l10n.mojito.service.branch.notification;

import com.box.l10n.mojito.entity.Branch;
import com.box.l10n.mojito.entity.BranchNotification;
import com.box.l10n.mojito.entity.BranchStatistic;
import com.box.l10n.mojito.entity.Screenshot;
import com.box.l10n.mojito.entity.ScreenshotTextUnit;
import com.box.l10n.mojito.service.branch.BranchRepository;
import com.box.l10n.mojito.service.branch.BranchStatisticRepository;
import com.box.l10n.mojito.service.branch.BranchStatisticService;
import com.box.l10n.mojito.service.branch.notification.job.BranchNotificationMissingScreenshotsJob;
import com.box.l10n.mojito.service.tm.search.TextUnitDTO;
import com.box.l10n.mojito.utils.DateTimeUtils;
import com.google.common.base.Joiner;
import org.apache.commons.codec.digest.DigestUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static org.slf4j.LoggerFactory.getLogger;

@Component
public class BranchNotificationService {

    /**
     * logger
     */
    static Logger logger = getLogger(BranchNotificationService.class);

    @Autowired
    BranchRepository branchRepository;

    @Autowired
    BranchNotificationRepository branchNotificationRepository;

    @Autowired
    BranchStatisticService branchStatisticService;

    @Autowired
    BranchNotificationMissingScreenshotsJob branchNotificationMissingScreenshotsJob;

    @Autowired
    BranchStatisticRepository branchStatisticRepository;

    @Autowired(required = false)
    List<BranchNotificationMessageSender> branchNotificationMessageSenders = new ArrayList<>();

    @Autowired
    DateTimeUtils dateTimeUtils;

    /**
     * When the state of branch changes, notifications must be send (new, updated, translated). This method sends
     * the required notification based on the current state of the branch.
     * <p>
     * It also schedules a job to check if screenshot are missing and send notification.
     *
     * @param branch
     */
    public void sendNotificationsForBranch(Long branchId) {
        logger.debug("sendNotificationsForBranch, id: {}", branchId);
        Branch branch = branchRepository.findOne(branchId);
        sendNotificationsForBranch(branch);
    }

    /**
     * If the branch was created more that X ({@link #scheduleMissingScreenshotNotificationsForBranch})
     * minutes ago and screenshot are still missing, send a notification.
     *
     * @param branchId
     */
    public void sendMissingScreenshotNotificationForBranch(Long branchId, String senderType) {
        logger.debug("sendMissingScreenshotNotificationForBranch, id: {}", branchId);
        BranchNotificationMessageSender branchNotificationMessageSender = findBySenderType(senderType);
        sendMissingScreenshotNotificationForBranchWithSender(branchNotificationMessageSender, branchId);
    }

    BranchNotificationMessageSender findBySenderType(String senderType) {
        return branchNotificationMessageSenders.stream().
                filter(s -> getSenderType(s).equals(senderType)).
                findFirst().
                orElseThrow(() -> new RuntimeException("Can't find sender for type: " + senderType));
    }

    void sendMissingScreenshotNotificationForBranchWithSender(BranchNotificationMessageSender branchNotificationMessageSender, Long branchId) {
        logger.debug("sendMissingScreenshotNotificationForBranch, id: {}", branchId);
        Branch branch = branchRepository.findOne(branchId);
        sendMissingScreenshotNotificationsForBranch(branchNotificationMessageSender, branch);
    }

    void sendNotificationsForBranch(Branch branch) {
        logger.debug("sendNotificationsForBranch: {} ({})", branch.getId(), branch.getName());
        for (BranchNotificationMessageSender branchNotificationMessageSender : branchNotificationMessageSenders) {
            try {
                sendNotificationsForBranchWithSender(branchNotificationMessageSender, branch);
            } catch (Exception e) {
                logger.error("Fail safe, error tracking is up to each sender", e);
            }
        }
    }

    void sendNotificationsForBranchWithSender(BranchNotificationMessageSender branchNotificationMessageSender, Branch branch) {
        String senderType = getSenderType(branchNotificationMessageSender);

        logger.debug("sendNotificationsForBranch: {} ({} with sender: {})", branch.getId(), branch.getName(), senderType);
        BranchNotificationInfo branchNotificationInfo = getBranchNotificationInfo(branch);
        BranchNotification branchNotification = getOrCreateBranchNotification(branch, senderType);

        if (shouldSendNewMessage(branchNotification, branchNotificationInfo)) {
            sendNewMessage(branchNotificationMessageSender, branch, branchNotification, branchNotificationInfo);
            scheduleMissingScreenshotNotificationsForBranch(branch, senderType);
        } else if (shouldSendUpdatedMessage(branchNotification, branchNotificationInfo)) {
            sendUpdatedMessage(branchNotificationMessageSender, branch, branchNotification, branchNotificationInfo);
            scheduleMissingScreenshotNotificationsForBranch(branch, senderType);
        }

        if (shouldSendTranslatedMessage(branch, branchNotification)) {
            sendTranslatedMessage(branchNotificationMessageSender, branch, branchNotification);
        }
    }

    /**
     * Schedule to check/send notification for missing screenshot in 30 minutes from now.
     *
     * @param branch
     * @param senderType
     */
    void scheduleMissingScreenshotNotificationsForBranch(Branch branch, String senderType) {
        Date date = DateTime.now().minusMinutes(30).toDate();
        branchNotificationMissingScreenshotsJob.schedule(branch.getId(), senderType, date);
    }

    void sendMissingScreenshotNotificationsForBranch(BranchNotificationMessageSender branchNotificationMessageSender, Branch branch) {
        logger.debug("sendMissingScreenshotNotificationForBranch: {} ({})", branch.getId(), branch.getName());

        BranchNotificationInfo branchNotificationInfo = getBranchNotificationInfo(branch);
        BranchNotification branchNotification = getOrCreateBranchNotification(branch, getSenderType(branchNotificationMessageSender));

        if (shouldSendScreenshotMissingMessage(branch, branchNotification)) {
            sendScreenshotMissingMessage(branchNotificationMessageSender, branch, branchNotification);
        }
    }

    void sendNewMessage(BranchNotificationMessageSender branchNotificationMessageSender,
                        Branch branch,
                        BranchNotification branchNotification,<commit_msg>The screenshot reminder should be sent 30 minutes after the branch is processed<commit_after>package com.box.l10n.mojito.service.branch.notification;

import com.box.l10n.mojito.entity.Branch;
import com.box.l10n.mojito.entity.BranchNotification;
import com.box.l10n.mojito.entity.BranchStatistic;
import com.box.l10n.mojito.entity.Screenshot;
import com.box.l10n.mojito.entity.ScreenshotTextUnit;
import com.box.l10n.mojito.service.branch.BranchRepository;
import com.box.l10n.mojito.service.branch.BranchStatisticRepository;
import com.box.l10n.mojito.service.branch.BranchStatisticService;
import com.box.l10n.mojito.service.branch.notification.job.BranchNotificationMissingScreenshotsJob;
import com.box.l10n.mojito.service.tm.search.TextUnitDTO;
import com.box.l10n.mojito.utils.DateTimeUtils;
import com.google.common.base.Joiner;
import org.apache.commons.codec.digest.DigestUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static org.slf4j.LoggerFactory.getLogger;

@Component
public class BranchNotificationService {

    /**
     * logger
     */
    static Logger logger = getLogger(BranchNotificationService.class);

    @Autowired
    BranchRepository branchRepository;

    @Autowired
    BranchNotificationRepository branchNotificationRepository;

    @Autowired
    BranchStatisticService branchStatisticService;

    @Autowired
    BranchNotificationMissingScreenshotsJob branchNotificationMissingScreenshotsJob;

    @Autowired
    BranchStatisticRepository branchStatisticRepository;

    @Autowired(required = false)
    List<BranchNotificationMessageSender> branchNotificationMessageSenders = new ArrayList<>();

    @Autowired
    DateTimeUtils dateTimeUtils;

    /**
     * When the state of branch changes, notifications must be send (new, updated, translated). This method sends
     * the required notification based on the current state of the branch.
     * <p>
     * It also schedules a job to check if screenshot are missing and send notification.
     *
     * @param branch
     */
    public void sendNotificationsForBranch(Long branchId) {
        logger.debug("sendNotificationsForBranch, id: {}", branchId);
        Branch branch = branchRepository.findOne(branchId);
        sendNotificationsForBranch(branch);
    }

    /**
     * If the branch was created more that X ({@link #scheduleMissingScreenshotNotificationsForBranch})
     * minutes ago and screenshot are still missing, send a notification.
     *
     * @param branchId
     */
    public void sendMissingScreenshotNotificationForBranch(Long branchId, String senderType) {
        logger.debug("sendMissingScreenshotNotificationForBranch, id: {}", branchId);
        BranchNotificationMessageSender branchNotificationMessageSender = findBySenderType(senderType);
        sendMissingScreenshotNotificationForBranchWithSender(branchNotificationMessageSender, branchId);
    }

    BranchNotificationMessageSender findBySenderType(String senderType) {
        return branchNotificationMessageSenders.stream().
                filter(s -> getSenderType(s).equals(senderType)).
                findFirst().
                orElseThrow(() -> new RuntimeException("Can't find sender for type: " + senderType));
    }

    void sendMissingScreenshotNotificationForBranchWithSender(BranchNotificationMessageSender branchNotificationMessageSender, Long branchId) {
        logger.debug("sendMissingScreenshotNotificationForBranch, id: {}", branchId);
        Branch branch = branchRepository.findOne(branchId);
        sendMissingScreenshotNotificationsForBranch(branchNotificationMessageSender, branch);
    }

    void sendNotificationsForBranch(Branch branch) {
        logger.debug("sendNotificationsForBranch: {} ({})", branch.getId(), branch.getName());
        for (BranchNotificationMessageSender branchNotificationMessageSender : branchNotificationMessageSenders) {
            try {
                sendNotificationsForBranchWithSender(branchNotificationMessageSender, branch);
            } catch (Exception e) {
                logger.error("Fail safe, error tracking is up to each sender", e);
            }
        }
    }

    void sendNotificationsForBranchWithSender(BranchNotificationMessageSender branchNotificationMessageSender, Branch branch) {
        String senderType = getSenderType(branchNotificationMessageSender);

        logger.debug("sendNotificationsForBranch: {} ({} with sender: {})", branch.getId(), branch.getName(), senderType);
        BranchNotificationInfo branchNotificationInfo = getBranchNotificationInfo(branch);
        BranchNotification branchNotification = getOrCreateBranchNotification(branch, senderType);

        if (shouldSendNewMessage(branchNotification, branchNotificationInfo)) {
            sendNewMessage(branchNotificationMessageSender, branch, branchNotification, branchNotificationInfo);
            scheduleMissingScreenshotNotificationsForBranch(branch, senderType);
        } else if (shouldSendUpdatedMessage(branchNotification, branchNotificationInfo)) {
            sendUpdatedMessage(branchNotificationMessageSender, branch, branchNotification, branchNotificationInfo);
            scheduleMissingScreenshotNotificationsForBranch(branch, senderType);
        }

        if (shouldSendTranslatedMessage(branch, branchNotification)) {
            sendTranslatedMessage(branchNotificationMessageSender, branch, branchNotification);
        }
    }

    /**
     * Schedule to check/send notification for missing screenshot in 30 minutes from now.
     *
     * @param branch
     * @param senderType
     */
    void scheduleMissingScreenshotNotificationsForBranch(Branch branch, String senderType) {
        Date date = DateTime.now().plusMinutes(30).toDate();
        branchNotificationMissingScreenshotsJob.schedule(branch.getId(), senderType, date);
    }

    void sendMissingScreenshotNotificationsForBranch(BranchNotificationMessageSender branchNotificationMessageSender, Branch branch) {
        logger.debug("sendMissingScreenshotNotificationForBranch: {} ({})", branch.getId(), branch.getName());

        BranchNotificationInfo branchNotificationInfo = getBranchNotificationInfo(branch);
        BranchNotification branchNotification = getOrCreateBranchNotification(branch, getSenderType(branchNotificationMessageSender));

        if (shouldSendScreenshotMissingMessage(branch, branchNotification)) {
            sendScreenshotMissingMessage(branchNotificationMessageSender, branch, branchNotification);
        }
    }

    void sendNewMessage(BranchNotificationMessageSender branchNotificationMessageSender,
                        Branch branch,
                        BranchNotification branchNotification,
{'fraction_non_alphanumeric': 0.07876834944504117, 'fraction_numerical': 0.004439670605084139, 'mean_word_length': 4.361228406909789, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2282677', 'n_tokens_mistral': 3466, 'n_tokens_neox': 3466, 'n_words': 673}