package ai.elimu.tasks;

import ai.elimu.dao.StoryBookChapterDao;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.logging.log4j.Logger;
import ai.elimu.dao.StoryBookDao;
import ai.elimu.dao.StoryBookParagraphDao;
import ai.elimu.dao.WordDao;
import ai.elimu.model.content.StoryBook;
import ai.elimu.model.content.StoryBookChapter;
import ai.elimu.model.content.StoryBookParagraph;
import ai.elimu.model.content.Word;
import ai.elimu.model.v2.enums.Language;
import ai.elimu.util.ConfigHelper;
import ai.elimu.util.WordFrequencyHelper;
import java.util.ArrayList;
import org.apache.logging.log4j.LogManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

/**
 * Iterates all StoryBooks and calculates the frequency of each word. Does not 
 * separate words with differing upper-case and lower-case letters.
 */
@Service
public class WordUsageCountScheduler {
    
    private Logger logger = LogManager.getLogger();

    @Autowired
    private WordDao wordDao;
    
    @Autowired
    private StoryBookDao storyBookDao;
    
    @Autowired
    private StoryBookChapterDao storyBookChapterDao;
    
    @Autowired
    private StoryBookParagraphDao storyBookParagraphDao;
    
    @Scheduled(cron="00 00 06 * * *") // At 06:00 every day
    public synchronized void execute() {
        logger.info("execute");
        
        logger.info("Calculating usage count for Words");

        Map<String, Integer> wordFrequencyMap = new HashMap<>();
        
        Language language = Language.valueOf(ConfigHelper.getProperty("content.language"));

        List<StoryBook> storyBooks = storyBookDao.readAllOrdered();
        logger.info("storyBooks.size(): " + storyBooks.size());
        for (StoryBook storyBook : storyBooks) {
            logger.info("storyBook.getTitle(): " + storyBook.getTitle());

            List<String> paragraphs = new ArrayList<>();
            List<StoryBookChapter> storyBookChapters = storyBookChapterDao.readAll(storyBook);
            for (StoryBookChapter storyBookChapter : storyBookChapters) {
                List<StoryBookParagraph> storyBookParagraphs = storyBookParagraphDao.readAll(storyBookChapter);
                for (StoryBookParagraph storyBookParagraph : storyBookParagraphs) {
                    paragraphs.add(storyBookParagraph.getOriginalText());
                }
            }

            Map<String, Integer> wordFrequencyMapForBook = WordFrequencyHelper.getWordFrequency(paragraphs, language);
            wordFrequencyMapForBook.keySet().forEach(word -> wordFrequencyMap.put(word, wordFrequencyMap.getOrDefault(word, 0) + wordFrequencyMapForBook.get(word)));
        }

        for (String key : wordFrequencyMap.keySet()) {
            String wordLowerCase = key.toLowerCase();
            logger.info("wordLowerCase: \"" + wordLowerCase + "\"");
            Word word = wordDao.readByText(wordLowerCase);
            if (word != null) {
                word.setUsageCount(wordFrequencyMap.get(wordLowerCase));
                
                // Temporary fix for "javax.validation.ConstraintViolationException"
                if (word.getLetterSoundCorrespondences() == null) {
                    logger.warn("Letter-sound correspondences not yet added. Skipping usage count update for word...");
                    continue;
                }
                
                wordDao.update(word);
            }
        }
        
        logger.info("execute complete");
    }
}

@@ -2801,19 +2801,20 @@
 (String 
-key
+word
  : wordF
@@ -2841,62 +2841,8 @@
 ) %7B%0A
-            String wordLowerCase = key.toLowerCase();%0A
     
@@ -2866,25 +2866,16 @@
 fo(%22word
-LowerCase
 : %5C%22%22 + 
@@ -2878,25 +2878,16 @@
 %22 + word
-LowerCase
  + %22%5C%22%22)
@@ -2905,17 +2905,25 @@
    Word 
-w
+existingW
 ord = wo
@@ -2943,25 +2943,16 @@
 ext(word
-LowerCase
 );%0A     
@@ -2962,17 +2962,25 @@
     if (
-w
+existingW
 ord != n
@@ -3002,17 +3002,25 @@
         
-w
+existingW
 ord.setU
@@ -3058,17 +3058,8 @@
 word
-LowerCase
 ));%0A
@@ -3180,17 +3180,25 @@
     if (
-w
+existingW
 ord.getL
@@ -3452,17 +3452,25 @@
 .update(
-w
+existingW
 ord);%0A  

Remove unnecessary `toLowerCase()`