class WordTools {

	static List<ParseWord> splitIntoParseWords(List<ParseTokens> parseTokensList, String chemicalName) {
		List<ParseTokens> wellFormedParseTokens = new ArrayList<ParseTokens>();//these are all in the same word as would be expected
		List<List<ParseTokens>> splitParseTokensForEachParseTokens = new ArrayList<List<ParseTokens>>();
		/*
		 * Each ParseTokens is split into the number of words it describes
		 * e.g. ethylchloride has one interpretation so splitParseTokensList will have one entry
		 * This entry will be formed of TWO parseTokens, one for the ethyl and one for the chloride
		 */
		int leastWordsInOmmittedSpaceParse = Integer.MAX_VALUE;//we want the least number of words i.e. less omitted spaces
		int longestFunctionalTermEncountered = 0;//we want the longest functional term
		for (ParseTokens parseTokens : parseTokensList) {
			List<Character> annotations = parseTokens.getAnnotations();
			List<List<Character>> chunkedAnnotations = chunkAnnotations(annotations);//chunked into mainGroup/substituent/functionalTerm
			if (containsOmittedSpace(chunkedAnnotations)){
				List<ParseTokens> omittedWordParseTokens = new ArrayList<ParseTokens>();
				List<String> tokens = parseTokens.getTokens();
				List<Character> newAnnotations = new ArrayList<Character>();
				List<String> newTokens = new ArrayList<String>();
				int currentFunctionalTermLength = 0;
				int annotPos = 0;
				for (List<Character> annotationList : chunkedAnnotations) {
					Character finalAnnotationInList = annotationList.get(annotationList.size() - 1);
					if (finalAnnotationInList.equals(END_OF_FUNCTIONALTERM) && newAnnotations.size() > 0) {
						//create a new parseTokens for the substituent/maingroup preceding the functional term
						//not necessary if the functional term is the first thing to be read e.g. in the case of poly
						omittedWordParseTokens.add(new ParseTokens(newTokens, newAnnotations));
						newAnnotations = new ArrayList<Character>();
						newTokens = new ArrayList<String>();
					}
					for (Character annotation : annotationList) {
						newAnnotations.add(annotation);
						newTokens.add(tokens.get(annotPos++));
					}
					if (finalAnnotationInList.equals(END_OF_FUNCTIONALTERM) || finalAnnotationInList.equals(END_OF_MAINGROUP) || annotPos == tokens.size()) {
						omittedWordParseTokens.add(new ParseTokens(newTokens, newAnnotations));
						if (finalAnnotationInList.equals(END_OF_FUNCTIONALTERM)){
							currentFunctionalTermLength = StringTools.stringListToString(newTokens, "").length();
						}
						newAnnotations = new ArrayList<Character>();
						newTokens = new ArrayList<String>();
					}
				}
				if (omittedWordParseTokens.size() <= leastWordsInOmmittedSpaceParse){
					if (omittedWordParseTokens.size() < leastWordsInOmmittedSpaceParse){
						splitParseTokensForEachParseTokens.clear();
						leastWordsInOmmittedSpaceParse = omittedWordParseTokens.size();
						longestFunctionalTermEncountered = 0;
					}
					if (currentFunctionalTermLength >=longestFunctionalTermEncountered){
						if (currentFunctionalTermLength > longestFunctionalTermEncountered){
							splitParseTokensForEachParseTokens.clear();
							longestFunctionalTermEncountered =currentFunctionalTermLength;
						}
						splitParseTokensForEachParseTokens.add(omittedWordParseTokens);
					}
				}
			} else {
				wellFormedParseTokens.add(parseTokens);
			}
		}
		List<ParseWord> parseWords = new ArrayList<ParseWord>();
		if (!wellFormedParseTokens.isEmpty()) {
			parseWords.add(new ParseWord(chemicalName, wellFormedParseTokens));
		} else {
			for (int i = 0; i < leastWordsInOmmittedSpaceParse; i++) {
				List<ParseTokens> parseTokensForWord = new ArrayList<ParseTokens>();
				for (List<ParseTokens> parseTokens : splitParseTokensForEachParseTokens) {
					if (!parseTokensForWord.contains(parseTokens.get(i))){//if only one word is ambiguous there is no need for the unambiguous word to have multiple identical interpretation
						parseTokensForWord.add(parseTokens.get(i));
					}
				}
				parseWords.add(new ParseWord(StringTools.stringListToString(parseTokensForWord.get(0).getTokens(), ""), parseTokensForWord));
			}
		}
		return parseWords;
	}

}