package org.eclipse.jst.validation.sample.parser;
/*
 * Licensed Material - Property of IBM 
 * (C) Copyright IBM Corp. 2002, 2003 - All Rights Reserved. 
 * US Government Users Restricted Rights - Use, duplication or disclosure 
 * restricted by GSA ADP Schedule Contract with IBM Corp. 
 *
 * DISCLAIMER OF WARRANTIES.
 * The following [enclosed] code is sample code created by IBM
 * Corporation. This sample code is not part of any standard or IBM
 * product and is provided to you solely for the purpose of assisting
 * you in the development of your applications.  The code is provided
 * "AS IS". IBM MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT
 * NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE, REGARDING THE FUNCTION OR PERFORMANCE OF
 * THIS CODE.  THIS CODE MAY CONTAIN ERRORS.  IBM shall not be liable
 * for any damages arising out of your use of the sample code, even
 * if it has been advised of the possibility of such damages.
 * 
 */

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;

/**
 * This class compares two .properties file and outputs a list
 * of the differences. This class is used to count the number
 * of words that have changed.
 */
public class CompareProperties {
	public static final String lineSeparator = java.lang.System.getProperty("line.separator"); //$NON-NLS-1$
	private TreeSet _deleted = null;
	private TreeMap _changed = null;
	private TreeSet _added = null;
	private PropertyFile _oldFile = null;
	private PropertyFile _newFile = null;

	/**
	 * This class is used to store PropertyLine instances which have the same
	 * message id, but different values. When the list of differences is output,
	 * all values are output so that the user can compare the lines manually, to
	 * see what's different.
	 */
	class CompareLine implements Comparable {
		private ArrayList _lines;
		private final String _messageId;

		public CompareLine(String messageId) {
			_messageId = messageId;
			_lines = new ArrayList();
		}

		public void add(PropertyLine oldLine, PropertyLine newLine) {
			_lines.add(new PropertyLine[]{oldLine, newLine});
		}

		public String toString() {
			StringBuffer buffer = new StringBuffer();
			Iterator iterator = _lines.iterator();
			while (iterator.hasNext()) {
				buffer.append(lineSeparator);
				buffer.append("\t"); //$NON-NLS-1$
				PropertyLine[] lines = (PropertyLine[])iterator.next();
				
				buffer.append(lines[0]);
				buffer.append("\n"); //$NON-NLS-1$
				buffer.append(lines[1]);
			}
			return buffer.toString();
		}

		/**
		 * Since this is a changed string, return the absolute difference of words between the strings.
		 */		
		public int getNumWords() {
			int numWords = 0;
			Iterator iterator = _lines.iterator();
			while (iterator.hasNext()) {
				PropertyLine[] lines = (PropertyLine[])iterator.next();
				numWords = numWords + compare(lines[0], lines[1]);
			}
			return numWords;
		}
		
		private int compare(PropertyLine oldLine, PropertyLine newLine) {
			// For every word in the old string, see if it exists in the new
			// string. The position of the word doesn't matter - if the word
			// exists in the new, then the word is not counted as a "changed"
			// word. 
			//    1. If the word exists, remove the word from the newLine and
			//       advance to the next old token. (Remove word from newLine
			//       in case the word existed twice in the old string but only
			//       once in the new. The second oldWord should be counted as
			//       a changed word.)
			//    2. If the word doesn't exist, numChanged++ and advance to the
			//       next old token.
			//    3. Once all of the oldWords have been checked, tokenize the
			//       remaining newWord and count the number of words in the string.
			//       These words have been added and each one counts as a 
			//       changed word.
			int numChangedWords = 0;
			StringTokenizer oldTokenizer = new StringTokenizer(oldLine.getMessage());

			// Need to be careful...want the entire word, not oldWord="on" mistaken for newWord="one" or newWord="bond"
			// Easier to create a list of new words to compare against.
			StringTokenizer newTokenizer = new StringTokenizer(newLine.getMessage());
			List newWords = new ArrayList(); // Can't use a set in case the newLine uses a word, e.g. "the", more than once.
			while(newTokenizer.hasMoreTokens()) {
				newWords.add(newTokenizer.nextToken());
			}
			
			while(oldTokenizer.hasMoreTokens()) {
				String oldWord = oldTokenizer.nextToken();
				if(newWords.contains(oldWord)) {
					newWords.remove(oldWord);
				}
				else {
					numChangedWords++;
				}
			}

			// Can count the tokens but not the elments.
			numChangedWords += newWords.size();
			return numChangedWords;
		}

		public String getMessageId() {
			return _messageId;
		}

		public int compareTo(Object o) {
			// by default, sort by message id
			if (!(o instanceof CompareLine)) {
				// then how on earth did this method get called??
				// put it at the end of the list
				return 1;
			}

			return getMessageId().compareTo(((CompareLine) o).getMessageId());
		}
	}

	/**
	 * Compare the two PropertyFile and print out a list of the differences; 
	 * the first parameter is the older .properties file, and the second 
	 * parameter is the newer .properties file.
	 */
	public CompareProperties(PropertyFile oldFile, PropertyFile newFile) {
		_deleted = new TreeSet();
		_changed = new TreeMap();
		_added = new TreeSet();
		
		_oldFile = oldFile;
		_newFile = newFile;

		compare(oldFile, newFile);
	}
	
	/**
	 * In the older PropertyFile, the message text was different; cache the
	 * older version of the PropertyLine and the newer version of the PropertyLine.
	 */
	private void addChanged(PropertyLine oldLine, PropertyLine newLine) {
		CompareLine cl = (CompareLine) _changed.get(oldLine.getMessageId());
		if (cl == null) {
			cl = new CompareLine(oldLine.getMessageId());
		}
		cl.add(oldLine, newLine);
		_changed.put(oldLine.getMessageId(), cl);
	}
	
	/**
	 * Compare the two property files and build the collections of variable names with
	 * their associated values.
	 */
	public void compare(PropertyFile oldFile, PropertyFile newFile) {
		_added.clear();
		_deleted.clear();
		_changed.clear();

		// For each element in file 1, see if it exists in file 2
		//   a) if it doesn't exist, add it to the list of "deleted" strings
		//   b) if it exists, and if the value is different, add it to the list of "changed" strings
		//   c) if it exists, and if the value is the same, add it to the list of "not changed" strings
		//   d) delete the entry, if it exists, from file 2's hashtable so we don't check it twice.
		// For each element in file 2 not checked already, it cannot exist in file 1, so add it to the list of "new" strings
		//
		// Need some way to abort comparison if either of the files contains duplicate
		// message ids.
		//
		List oldKeys = new ArrayList(oldFile.getPropertyLines());
		List newKeys = new ArrayList(newFile.getPropertyLines());
		Collections.sort(oldKeys, PropertyLineComparator.getMessageIdComparator());
		Collections.sort(newKeys, PropertyLineComparator.getMessageIdComparator());
		Iterator oldIterator = oldKeys.iterator();
		Iterator newIterator = newKeys.iterator();
		PropertyLine oldLine = (oldIterator.hasNext()) ? (PropertyLine) oldIterator.next() : null;
		PropertyLine newLine = (newIterator.hasNext()) ? (PropertyLine) newIterator.next() : null;
		while ((oldLine != null) && (newLine != null)) {
			// oldLine message id is either <, =, or > newLine message id.
			// if <, message id has been deleted.
			// if =, see if changed (or just compare message ids.)
			// if >, new line is a new message id.
			// to increment, increment only the < (whether it's oldLine or newLine).
			int compare = oldLine.getMessageId().compareTo(newLine.getMessageId());
			if (compare < 0) {
				// deleted
				_deleted.add(oldLine);
				if (oldIterator.hasNext()) {
					oldLine = (PropertyLine) oldIterator.next();
				}
				else {
					oldLine = null;
				}
			}
			else if (compare == 0) {
				// existed before. Check if changed.
				if (!oldLine.getMessage().equals(newLine.getMessage())) {
					// changed
					addChanged(oldLine, newLine);
				}
				if (oldIterator.hasNext() && newIterator.hasNext()) {
					oldLine = (PropertyLine) oldIterator.next();
					newLine = (PropertyLine) newIterator.next();
				}
				else {
					oldLine = null;
					newLine = null;
				}

			}
			else {
				// added
				_added.add(newLine);
				if (newIterator.hasNext()) {
					newLine = (PropertyLine) newIterator.next();
				}
				else {
					newLine = null;
				}
			}
		}

		if (oldLine != null) {
			_deleted.add(oldLine);
		}

		if (newLine != null) {
			_added.add(newLine);
		}

		while (oldIterator.hasNext()) {
			// all of the rest have been deleted
			_deleted.add(oldIterator.next());
		}

		while (newIterator.hasNext()) {
			// all of the rest have been added
			_added.add(newIterator.next());
		}
	}
	
	/**
	 * Return a Collction of PropertyLine instances that exist in
	 * the newer PropertyFile that aren't in the older PropertyFile.
	 */
	public Set getAdded() {
		return _added;
	}
	
	/**
	 * Return a Collection of CompareLine instances that represent
	 * the two PropertyLine instances; one from the older PropertyFile,
	 * and one from the newer PropertyFile.
	 */
	public Collection getChanged() {
		return _changed.values();
	}
	
	/**
	 * Return a Collection of PropertyLine instances that do not
	 * exist in the newer PropertyFile yet that exist in the older
	 * PropertyFile.
	 */
	public Set getDeleted() {
		return _deleted;
	}
	
	/**
	 * Print out all of the collections of variable strings.
	 */
	public void printResults() {
		// create an output log in the current directory, and in it list the strings in a section each.
		int numNew = printStrings("NEW PROPERTIES", _added); //$NON-NLS-1$
		
		int numWordsDeleted = printStrings("DELETED PROPERTIES", _deleted); //$NON-NLS-1$
		int numWordsChanged =  printStrings("CHANGED PROPERTIES", _changed.values()); //$NON-NLS-1$
		float totalChange = numNew + numWordsDeleted + numWordsChanged;
		float numWords = _newFile.getNumWords();
		float percent = totalChange / numWords * 100;
		
		System.out.println();
		System.out.println("Number of new words: " + numNew); //$NON-NLS-1$
		System.out.println("Number of words in deleted messages: " + numWordsDeleted); //$NON-NLS-1$
		System.out.println("Number of changed words in modified messages: " + numWordsChanged); //$NON-NLS-1$
		System.out.println("Number of words in file " + _newFile.getQualifiedFileName() + ": " + numWords); //$NON-NLS-1$ //$NON-NLS-2$
		System.out.println("Total change of words: " + totalChange + ", which is a " + percent + "% change."); //$NON-NLS-1$  //$NON-NLS-2$ //$NON-NLS-3$
	}
	
	public void printResultsForTranslation() {
		// create an output log in the current directory, and in it list the strings in a section each.
		printStringsForTranslation("DELETED PROPERTIES", _deleted); //$NON-NLS-1$
		printStringsForTranslation("NEW PROPERTIES", _added); //$NON-NLS-1$
		printStringsForTranslation("CHANGED PROPERTIES", _changed.values()); //$NON-NLS-1$
	}
	
	/**
	 * Print the number of lines in the .properties file.
	 */
	private int printStrings(String header, Collection lines) {
		System.out.println();
		System.out.println(header);
		int count = 0;
		int numWords = 0;
		Iterator iterator = lines.iterator();
		while (iterator.hasNext()) {
			Object line = iterator.next();
			if(line instanceof PropertyLine) {
				numWords += ((PropertyLine)line).getNumWords();
			}
			else {
				// must be a compare line
				numWords += ((CompareLine)line).getNumWords();
			}
			
			count++;
			System.out.println(line);
		}
		System.out.println("Number of properties: " + count); //$NON-NLS-1$
		System.out.println();
		return numWords;
	}
	
	/**
	 * Print the contents of the sorted collection of lines from the .properties file.
	 */
	private void printStringsForTranslation(String header, Collection lines) {
		System.out.println();
		System.out.println(header);
		int count = 0;
		Iterator iterator = lines.iterator();
		while (iterator.hasNext()) {
			count++;
			Object line = iterator.next();
			if (line instanceof PropertyLine) {
				PropertyLine propline = (PropertyLine) line;
				System.out.println(propline.getMessageId());
			}
			else if (line instanceof CompareLine) {
				CompareLine propline = (CompareLine) line;
				System.out.println(propline.getMessageId());
			}
			else {
				System.out.println("instance of " + line.getClass().getName()); //$NON-NLS-1$
			}
		}
		System.out.println("Total: " + count); //$NON-NLS-1$
		System.out.println();
	}
}