/*******************************************************************************
 * Copyright (c) 2000, 2008 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.wst.jsdt.internal.ui.compare;

import java.io.IOException;

import org.eclipse.compare.CompareUI;
import org.eclipse.compare.IEditableContent;
import org.eclipse.compare.ISharedDocumentAdapter;
import org.eclipse.compare.IStreamContentAccessor;
import org.eclipse.compare.ITypedElement;
import org.eclipse.compare.structuremergeviewer.DocumentRangeNode;
import org.eclipse.compare.structuremergeviewer.IStructureComparator;
import org.eclipse.compare.structuremergeviewer.StructureCreator;
import org.eclipse.compare.structuremergeviewer.StructureRootNode;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.rules.FastPartitioner;
import org.eclipse.swt.graphics.Image;
import org.eclipse.wst.jsdt.internal.ui.JavaScriptPlugin;
import org.eclipse.wst.jsdt.internal.ui.propertiesfileeditor.IPropertiesFilePartitions;
import org.eclipse.wst.jsdt.internal.ui.propertiesfileeditor.PropertiesFilePartitionScanner;


public class PropertiesStructureCreator extends StructureCreator {
	
	/**
	 * A PropertyNode represents a key/value pair of a Java property file.
	 * The text range of a leg/value pair starts with an optional
	 * comment and ends right after the value.
	 */
	static class PropertyNode extends DocumentRangeNode implements ITypedElement, IAdaptable {
		
		public PropertyNode(DocumentRangeNode parent, int type, String id, String value, IDocument doc, int start, int length) {
			super(parent, type, id, doc, start, length);
			if (parent != null) {
				parent.addChild(this);
			}
		}
							
		/* (non Java doc)
		 * see ITypedElement#getName
		 */
		public String getName() {
			return getId();
		}

		/* (non Java doc)
		 * see ITypedElement#getType
		 */
		public String getType() {
			return "properties2"; //$NON-NLS-1$
		}
		
		/* (non Java doc)
		 * see ITypedElement#getImage
		 */
		public Image getImage() {
			return CompareUI.getImage(getType());
		}
	}
	
	private static final String WHITESPACE= " \t\r\n\f"; //$NON-NLS-1$
	private static final String SEPARATORS= "=:"; //$NON-NLS-1$
	private static final String SEPARATORS2= SEPARATORS + WHITESPACE;
			

	public PropertiesStructureCreator() {
	}
	
	public String getName() {
		return CompareMessages.PropertyCompareViewer_title; 
	}
	
	protected IStructureComparator createStructureComparator(Object input,
			IDocument document, ISharedDocumentAdapter sharedDocumentAdapter,
			IProgressMonitor monitor) throws CoreException {
		
		final boolean isEditable;
		if (input instanceof IEditableContent)
			isEditable= ((IEditableContent) input).isEditable();
		else
			isEditable= false;

		DocumentRangeNode root= new StructureRootNode(document, input, this, sharedDocumentAdapter) {
			public boolean isEditable() {
				return isEditable;
			}
		};
				
		try {
			monitor = beginWork(monitor);
			parsePropertyFile(root, document, monitor);
		} catch (IOException ex) {
			if (sharedDocumentAdapter != null)
				sharedDocumentAdapter.disconnect(input);
			throw new CoreException(new Status(IStatus.ERROR, JavaScriptPlugin.getPluginId(), 0, CompareMessages.PropertiesStructureCreator_error_occurred, ex));
		} finally {
			monitor.done();
		}
		
		return root;
	}
		
	public IStructureComparator locate(Object path, Object source) {
		return null;
	}
	
	public String getContents(Object node, boolean ignoreWhitespace) {
		if (node instanceof IStreamContentAccessor) {
			IStreamContentAccessor sca= (IStreamContentAccessor) node;
			try {
				return JavaCompareUtilities.readString(sca);
			} catch (CoreException ex) {
				JavaScriptPlugin.log(ex);
			}
		}
		return null;
	}
	
	private String readLine(int[] args, IDocument doc) {
		int line= args[0]++;
		try {
			IRegion region= doc.getLineInformation(line);
			int start= region.getOffset();
			int length= region.getLength();
			
			try {
				region= doc.getLineInformation(line+1);
				args[1]= region.getOffset();
			} catch (BadLocationException ex) {
				args[1]= doc.getLength();
			}
			
			return doc.get(start, length);
		} catch (BadLocationException ex) {
			// silently ignored
		}
		return null;
	}
			
	private void parsePropertyFile(DocumentRangeNode root, IDocument doc, IProgressMonitor monitor) throws IOException {
		
		int start= -1;
		int lineStart= 0;
		
		int[] args= new int[2];
		args[0]= 0;	// here we return the line number
		args[1]= 0;	// and here the offset of the first character of the line 
		
		for (;;) {
			worked(monitor);
			lineStart= args[1];	// start of current line
            String line= readLine(args, doc);
			if (line == null)
				return;
				
			if (line.length() <= 0)
				continue;	// empty line
				
			char firstChar= line.charAt(0);
			if (firstChar == '#' || firstChar == '!') {
				if (start < 0)	// comment belongs to next key/value pair
					start= lineStart;	
				continue;	// comment
			}
								
			// find continuation lines
			while (needNextLine(line)) {
				String nextLine= readLine(args, doc);
				if (nextLine == null)
					nextLine= ""; //$NON-NLS-1$
				String line2= line.substring(0, line.length()-1);
				int startPos= 0;
				for (; startPos < nextLine.length(); startPos++)
					if (WHITESPACE.indexOf(nextLine.charAt(startPos)) == -1)
						break;
				nextLine= nextLine.substring(startPos, nextLine.length());
				line= line2 + nextLine;
			}
			
    		// key start
    		int len= line.length();
    		int keyPos= 0;
    		for (; keyPos < len; keyPos++) {
       			if (WHITESPACE.indexOf(line.charAt(keyPos)) == -1)
            		break;
    		}
    		
    		// key/value separator
    		int separatorPos;
    		for (separatorPos= keyPos; separatorPos < len; separatorPos++) {
        		char c= line.charAt(separatorPos);
        		if (c == '\\')
            		separatorPos++;
        		else if (SEPARATORS2.indexOf(c) != -1)
            		break;
    		}

     		int valuePos;
    		for (valuePos= separatorPos; valuePos < len; valuePos++)
        		if (WHITESPACE.indexOf(line.charAt(valuePos)) == -1)
            		break;

     		if (valuePos < len)
        		if (SEPARATORS.indexOf(line.charAt(valuePos)) != -1)
            		valuePos++;

     		while (valuePos < len) {
        		if (WHITESPACE.indexOf(line.charAt(valuePos)) == -1)
            		break;
        		valuePos++;
    		}
    
    		String key= convert(line.substring(keyPos, separatorPos));
    		if (key.length() > 0) {
    					
 				if (start < 0)
					start= lineStart;
    			
	    		String value= ""; //$NON-NLS-1$
				if (separatorPos < len)
					value= convert(line.substring(valuePos, len));
										    		
	    		int length= args[1] - start;
	    		
				try {
					String s= doc.get(start, length);
					for (int i= s.length()-1; i >= 0; i--) {
						char c= s.charAt(i);
						if (c !='\r' && c != '\n')
							break;
						length--;
					}
				} catch (BadLocationException e) {
					// silently ignored
				}
	    		
	     		new PropertyNode(root, 0, key, value, doc, start, length);
 				start= -1;
   			}
		}
	}

	private boolean needNextLine(String line) {
		int slashes= 0;
		int ix= line.length() - 1;
		while ((ix >= 0) && (line.charAt(ix--) == '\\'))
			slashes++;
		return slashes % 2 == 1;
	}

	/*
	 * Converts escaped characters to Unicode.
	 */
	private String convert(String s) {
		int l= s.length();
		StringBuffer buf= new StringBuffer(l);
		int i= 0;
		
		while (i < l) {
			char c= s.charAt(i++);
			if (c == '\\') {
				c= s.charAt(i++);
				if (c == 'u') {
					int v= 0;
					for (int j= 0; j < 4; j++) {
						c= s.charAt(i++);
				        switch (c) {
				        case '0': case '1': case '2': case '3': case '4':
				        case '5': case '6': case '7': case '8': case '9':
							v= (v << 4) + (c-'0');
					     	break;
						case 'a': case 'b': case 'c':
		     			case 'd': case 'e': case 'f':
							v= (v << 4) + 10+(c-'a');
							break;
						case 'A': case 'B': case 'C':
		                case 'D': case 'E': case 'F':
							v= (v << 4) + 10+(c - 'A');
							break;
						default:
		             		throw new IllegalArgumentException(CompareMessages.PropertyCompareViewer_malformedEncoding); 
		                }
					}
					buf.append((char)v);
				} else {
					switch (c) {
					case 't':
		    			c= '\t';
						break;
					case 'r':
		    			c= '\r';
						break;
					case 'n':
		    			c= '\n';
						break;
					case 'f':
		    			c= '\f';
						break;
					}
		            buf.append(c);
				}
			} else
				buf.append(c);
		}
		return buf.toString();
	}

	protected IDocumentPartitioner getDocumentPartitioner() {
		return new FastPartitioner(new PropertiesFilePartitionScanner(), IPropertiesFilePartitions.PARTITIONS);
	}
	
	protected String getDocumentPartitioning() {
		return IPropertiesFilePartitions.PROPERTIES_FILE_PARTITIONING;
	}
	
	private void worked(IProgressMonitor monitor) {
		if (monitor.isCanceled())
			throw new OperationCanceledException();
		monitor.worked(1);
	}

	private IProgressMonitor beginWork(IProgressMonitor monitor) {
		if (monitor == null)
			return new NullProgressMonitor();
		return new SubProgressMonitor(monitor, IProgressMonitor.UNKNOWN);
	}
	
}
