package com.alexrnl.subtitlecorrector.correctionstrategy;

import static com.alexrnl.subtitlecorrector.common.TranslationKeys.KEYS;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.alexrnl.commons.utils.Word;
import com.alexrnl.subtitlecorrector.common.Subtitle;
import com.alexrnl.subtitlecorrector.service.DictionaryManager;

/**
 * Strategy for replacing a letter by an other in subtitles.
 * @author Alex
 */
public class LetterReplacement implements Strategy {
	/** Logger */
	private static Logger				lg	= Logger.getLogger(LetterReplacement.class.getName());
	
	/** The dictionary manager used in the application */
	private final DictionaryManager		dictionaryManager;
	/** The original letter to replace */
	private final Parameter<Character>	originalLetter;
	/** The new letter to put */
	private final Parameter<Character>	newLetter;
	/** Flag indicating to replace only in word which are not in the dictionary */
	private final Parameter<Boolean>	onlyMissingFromDictionary;
	/** Flag indicating to prompt user each time before replacing the letter */
	private final Parameter<Boolean>	promptBeforeCorrecting;

	/**
	 * Constructor #1.<br />
	 * @param dictionaryManager
	 *        the dictionary manager to use.
	 */
	public LetterReplacement (final DictionaryManager dictionaryManager) {
		super();
		this.dictionaryManager = dictionaryManager;
		originalLetter = new Parameter<>(ParameterType.FREE, KEYS.strategy().letterReplacement().originalLetter());
		newLetter = new Parameter<>(ParameterType.FREE, KEYS.strategy().letterReplacement().newLetter());
		onlyMissingFromDictionary = new Parameter<>(ParameterType.BOOLEAN, KEYS.strategy().letterReplacement().onlyMissingFromDictionary(), false, true);
		promptBeforeCorrecting = new Parameter<>(ParameterType.BOOLEAN, KEYS.strategy().letterReplacement().promptBeforeCorrecting(), false, true);
	}

	@Override
	public List<Parameter<?>> getParameters () {
		final List<Parameter<?>> parameters = new ArrayList<>(4);
		parameters.add(originalLetter);
		parameters.add(newLetter);
		parameters.add(onlyMissingFromDictionary);
		parameters.add(promptBeforeCorrecting);
		return parameters;
	}
	
	@Override
	public void correct (final Subtitle subtitle) {
		if (!subtitle.getContent().contains(originalLetter.getValue().toString())) {
			// Skip subtitles which are not concerned
			if (lg.isLoggable(Level.FINE)) {
				lg.fine("Skipping subtitle " + subtitle);
			}
			return;
		}
		
		String remaining = subtitle.getContent();
		final StringBuilder newContent = new StringBuilder();
		while (!remaining.isEmpty()) {
			final Word currentWord = Word.getNextWord(remaining);
			newContent.append(remaining.substring(0, currentWord.getBegin() - 1));
			remaining = remaining.substring(currentWord.getEnd());
			
			if (!currentWord.getWord().contains(originalLetter.getValue().toString())) {
				// The letter to replace is not in the word
				newContent.append(currentWord);
				continue;
			}
			
			if (onlyMissingFromDictionary.getValue() && dictionaryManager.contains(currentWord.getWord())) {
				// The current word is in the dictionary
				continue;
			}
			
			final String replacement = currentWord.getWord().replaceAll(
					originalLetter.getValue().toString(), newLetter.getValue().toString());
			
			if (promptBeforeCorrecting.getValue()) {
				// replacement = prompt.confirm(subtitle.getContent(), currentWord, replacement);
				// TODO prompt for auto correction on next occurrence of word?
			}
			newContent.append(replacement);
		}
		
		if (lg.isLoggable(Level.FINE)) {
			lg.fine("Replacing subtitle content '" + subtitle.getContent() + "' with '" + newContent + "'");
		}
		
		subtitle.setContent(newContent.toString());
	}
}

@@ -399,16 +399,136 @@
 Manager;
+%0Aimport com.alexrnl.subtitlecorrector.service.UserPrompt;%0Aimport com.alexrnl.subtitlecorrector.service.UserPromptAnswer;
 %0A%0A/**%0A *
@@ -864,24 +864,91 @@
 aryManager;%0A
+%09/** The user prompt to use */%0A%09private final UserPrompt%09%09%09prompt;%0A
 %09/** The ori
@@ -1482,16 +1482,64 @@
 to use.%0A
+%09 * @param prompt%0A%09 *        the prompt to use.%0A
 %09 */%0A%09pu
@@ -1603,16 +1603,41 @@
 yManager
+, final UserPrompt prompt
 ) %7B%0A%09%09su
@@ -1689,16 +1689,40 @@
 anager;%0A
+%09%09this.prompt = prompt;%0A
 %09%09origin
@@ -3457,16 +3457,52 @@
 tionary%0A
+%09%09%09%09newContent.append(currentWord);%0A
 %09%09%09%09cont
@@ -3519,22 +3519,16 @@
 %0A%09%09%09%0A%09%09%09
-final 
 String r
@@ -3707,22 +3707,37 @@
 %09%09%09%09
-// replacement
+final UserPromptAnswer answer
  = p
@@ -3808,42 +3808,174 @@
 %09%09%09%09
-// TODO prompt for auto c
+if (answer.isCancelled()) %7B%0A%09%09%09%09%09newContent.append(currentWord);%0A%09%09%09%09%09continue;%0A%09%09%09%09%7D%0A%09%09%09%09if (answer.isRememberChoice()) %7B%0A%09%09%09%09%09// TODO add choice to map f
 or
+ 
 re
-ction
+member
  on 
@@ -3988,22 +3988,57 @@
 ccur
-rence of word?
+ences%0A%09%09%09%09%7D%0A%09%09%09%09replacement = answer.getAnswer();
 %0A%09%09%09

Use UserPrompt in LetterReplacement strategy