/*******************************************************************************
 * Copyright (c) 2000, 2011 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Brock Janiczak <brockj@tpg.com.au> - Bug 179977 CVS log command doesn't scale well with lots of tags and versions
 *     Brock Janiczak <brockj@tpg.com.au> - Bug 194396 Reduce retained memory usage of LogEntry objects
 *     Olexiy Buyanskyy <olexiyb@gmail.com> - Bug 76386 - [History View] CVS Resource History shows revisions from all branches
 *******************************************************************************/
package org.eclipse.team.internal.ccvs.core.client.listeners;

import java.text.*;
import java.util.*;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.osgi.util.NLS;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.client.CommandOutputListener;
import org.eclipse.team.internal.ccvs.core.resources.RemoteFile;
import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo;
import org.eclipse.team.internal.ccvs.core.util.Util;

/**
 * Log listener that parses the log entries returned from the
 * server but delegates the handling of the entries to a subclass.
 */
public class LogListener extends CommandOutputListener {
	
	/*
	 * A new format for log dates was introduced in 1.12.9
	 */
	private static final String LOG_TIMESTAMP_FORMAT_OLD= "yyyy/MM/dd HH:mm:ss zzz";//$NON-NLS-1$
	private static final String LOG_TIMESTAMP_FORMAT= "yyyy-MM-dd HH:mm:ss zzz";//$NON-NLS-1$
	private static final Locale LOG_TIMESTAMP_LOCALE= Locale.US;
	private final DateFormat LOG_DATE_FORMATTER_OLD = new SimpleDateFormat(LOG_TIMESTAMP_FORMAT_OLD, LOG_TIMESTAMP_LOCALE);
	private final DateFormat LOG_DATE_FORMATTER = new SimpleDateFormat(LOG_TIMESTAMP_FORMAT, LOG_TIMESTAMP_LOCALE);
	
	// Server message prefix used for error detection
	private static final String NOTHING_KNOWN_ABOUT = "nothing known about "; //$NON-NLS-1$

	// States of log accumulation.
	private final int DONE = 4;
	private final int COMMENT = 3;
	private final int REVISION = 2;
	private final int SYMBOLIC_NAMES = 1;
	private final int BEGIN = 0;
	
	//Tag used for accumulating all of a branch's revision info
	public final static String BRANCH_REVISION = "branchRevision"; //$NON-NLS-1$
	
	private static final CVSTag[] NO_TAGS = new CVSTag[0];
	private static final String[] NO_VERSIONS = new String[0];
	
	// Instance variables for accumulating Log information
	private RemoteFile currentFile;
	private int state = BEGIN;
	private StringBuffer comment;
	private String fileState;
	private String revision;
	private String author;
	private Date creationDate;
	private List versions = new ArrayList();
	private Map internedStrings = new HashMap();
	private final ILogEntryListener listener;
	
	/**
	 * Create a log listener for receiving entries for one or more files.
	 */
	public LogListener(ILogEntryListener listener) {
		this.listener = listener;
	}

	public LogListener(RemoteFile file, ILogEntryListener listener) {
		this(listener);
		this.currentFile = file;   
	}

	private String getRelativeFilePath(ICVSRepositoryLocation location, String fileName) {
		if (fileName.endsWith(",v")) { //$NON-NLS-1$
			fileName = fileName.substring(0, fileName.length() - 2);
		}
		fileName = Util.removeAtticSegment(fileName);
		String rootDirectory = location.getRootDirectory();
		if (fileName.startsWith(rootDirectory)) {
			try {
				fileName = Util.getRelativePath(rootDirectory, fileName);
			} catch (CVSException e) {
				CVSProviderPlugin.log(e);
				return null;
			}
		}
		return fileName;
	}

	public IStatus errorLine(String line, ICVSRepositoryLocation location, ICVSFolder commandRoot, IProgressMonitor monitor) {
		String serverMessage = getServerMessage(line, location);
		if (serverMessage != null) {
			// look for the following condition
			// E cvs server: nothing known about fileName
			if (serverMessage.startsWith(NOTHING_KNOWN_ABOUT)) {
				return new CVSStatus(IStatus.ERROR, CVSStatus.DOES_NOT_EXIST, line, commandRoot);
			}
		}
		return OK;
	}

	public IStatus messageLine(String line, ICVSRepositoryLocation location, ICVSFolder commandRoot, IProgressMonitor monitor) {
		// Fields we will find in the log for a file
		// keys = String (tag name), values = String (tag revision number) */
		switch (state) {
			case BEGIN:
				if (line.startsWith("RCS file: ")) { //$NON-NLS-1$
					// We are starting to recieve the log for a file
					String fileName = getRelativeFilePath(location, line.substring(10).trim());
					if (fileName == null) {
						currentFile = null;
						handleInvalidFileName(location, fileName);
					} else {
						if (currentFile == null || !currentFile.getRepositoryRelativePath().equals(fileName)) {
							// We are starting another file
							beginFile(location, fileName);
						}
					}
				} else  if (line.startsWith("symbolic names:")) { //$NON-NLS-1$
					state = SYMBOLIC_NAMES;
				} else if (line.startsWith("revision ")) { //$NON-NLS-1$
					// if the revision has been locked, remove the "locked by" suffix 
					revision = line.substring(9).replaceFirst(ResourceSyncInfo.LOCKEDBY_REGEX, ""); //$NON-NLS-1$
					revision = internAndCopyString(revision);
					state = REVISION;
				} else if (line.startsWith("total revisions:")){ //$NON-NLS-1$
					//if there are no current revision selected and this is a branch then we are in the 
					//case where there have been no changes made on the branch since the initial branching
					//and we need to get the revision that the branch was made from
					int indexOfSelectedRevisions = line.lastIndexOf("selected revisions: "); //$NON-NLS-1$
					//20 for length of "selected revisions: "
					String selectedRevisions = line.substring(indexOfSelectedRevisions + 20).trim();
					if (selectedRevisions.equals("0")){ //$NON-NLS-1$
						//ok put into comment state to await ======= and add info to log
						state = COMMENT;
						revision = BRANCH_REVISION;
						comment = new StringBuffer();
					}
				}
				break;
			case SYMBOLIC_NAMES:
				if (line.startsWith("keyword substitution:")) { //$NON-NLS-1$
					state = BEGIN;
				} else {
					int firstColon = line.indexOf(':');
					String tagName = internAndCopyString(line.substring(1, firstColon));
					String tagRevision = internAndCopyString(line.substring(firstColon + 2));
					versions.add(new VersionInfo(tagRevision, tagName));
				}
				break;
			case REVISION:
				// date: 2000/06/19 04:56:21;  author: somebody;  state: Exp;  lines: +114 -45
				// get the creation date
				int endOfDateIndex = line.indexOf(';', 6);
				creationDate = convertFromLogTime(line.substring(6, endOfDateIndex) + " GMT"); //$NON-NLS-1$
	
				// get the author name
				int endOfAuthorIndex = line.indexOf(';', endOfDateIndex + 1);
				author = internAndCopyString(line.substring(endOfDateIndex + 11, endOfAuthorIndex));

				// get the file state (because this revision might be "dead")
				int endOfStateIndex = line.indexOf(';', endOfAuthorIndex + 1) < 0 ? line.length() : line.indexOf(';', endOfAuthorIndex + 1);
				fileState = internAndCopyString(line.substring(endOfAuthorIndex + 10, endOfStateIndex));
				comment = new StringBuffer();
				state = COMMENT;
				break;
			case COMMENT:
				// skip next line (info about branches) if it exists, if not then it is a comment line.
				if (line.startsWith("branches:")) break; //$NON-NLS-1$
				if (line.equals("=============================================================================") //$NON-NLS-1$
					|| line.equals("----------------------------")) { //$NON-NLS-1$
					state = DONE;
					break;
				}
				//check for null if we are in the waiting to finish case (brought on by branches)
				if (comment == null)
					break; 
				
				if (comment.length() != 0) comment.append('\n');
				comment.append(line);
				break;
		}
		if (state == DONE) {
			// we are only interested in tag names for this revision, remove all others.
			List thisRevisionTags = versions.isEmpty() ? Collections.EMPTY_LIST : new ArrayList(3);
			List thisRevisionBranches = new ArrayList(1);
			//a parallel lists for revision tags (used only for branches with no commits on them)
			List revisionVersions = versions.isEmpty() ? Collections.EMPTY_LIST : new ArrayList(3);
			String branchRevision = this.getBranchRevision(revision);
			for (Iterator i = versions.iterator(); i.hasNext();) {
				VersionInfo version = (VersionInfo) i.next();
				String tagName = version.getTagName();
				String tagRevision = version.getTagRevision();
				String tagBranchRevision = version.getBranchRevision();
				int type = version.isBranch() ? CVSTag.BRANCH : CVSTag.VERSION;
				if ( branchRevision.equals(tagBranchRevision) || 
						(version.isBranch() && revision.equals(tagRevision))) {
					CVSTag cvsTag = new CVSTag(tagName, tagBranchRevision, type);
					thisRevisionBranches.add(cvsTag);
				}
				
				if (tagRevision.equals(revision) ||
					revision.equals(BRANCH_REVISION)) {
					CVSTag cvsTag = new CVSTag(tagName, tagBranchRevision, type);
					thisRevisionTags.add(cvsTag);
					if (revision.equals(BRANCH_REVISION)){
						//also record the tag revision
						revisionVersions.add(tagRevision);
					}
				}
			}
			
			if (branchRevision.equals(CVSTag.HEAD_REVISION)) {
				CVSTag tag = new CVSTag(CVSTag.HEAD_BRANCH, CVSTag.HEAD_REVISION, CVSTag.HEAD);
				thisRevisionBranches.add(tag);
			} else {
				if ( thisRevisionBranches.size() == 0) {
					CVSTag cvsTag = new CVSTag(CVSTag.UNKNOWN_BRANCH, branchRevision, CVSTag.BRANCH);
					thisRevisionBranches.add(cvsTag);
				}			
			}
			if (currentFile != null) {
				LogEntry entry = new LogEntry(currentFile, revision, author, creationDate,
					internString(comment.toString()), fileState, 
					!thisRevisionTags.isEmpty() ? (CVSTag[]) thisRevisionTags.toArray(new CVSTag[thisRevisionTags.size()]) :NO_TAGS, 
					!thisRevisionBranches.isEmpty() ? (CVSTag[]) thisRevisionBranches.toArray(new CVSTag[thisRevisionBranches.size()]) :NO_TAGS, 
						!revisionVersions.isEmpty() ? (String[]) revisionVersions.toArray(new String[revisionVersions.size()]) : NO_VERSIONS);
				addEntry(entry);
			}
			state = BEGIN;
		}
		return OK;
	}

	/**
	 * Convert revision number to branch number.
	 * 
	 * <table border="1">
	 * <tr><th>revision</th><th>branch</th><th>comment</th></tr>
	 * <tr><td>1.1.2.1</td><td>1.1.0.2</td><td>regular branch</td></tr>
	 * <tr><td>1.1.4.1</td><td>1.1.0.4</td><td>regular branch</td></tr>
	 * <tr><td>1.1.1.2</td><td>1.1.1</td><td>vendor branch</td></tr>
	 * <tr><td>1.1.2.1.2.3</td><td>1.1.2.1.0.2</td><td>branch created from another branch</td></tr>
	 * </table>
	 * 
	 * @param revision revision number
	 * @return branch number
	 * 
	 */
	private String getBranchRevision(String revision) {
		if (revision.length() == 0 || revision.lastIndexOf(".") == -1) //$NON-NLS-1$
			throw new IllegalArgumentException(
					"Revision malformed: " + revision); //$NON-NLS-1$
		String branchNumber = revision.substring(0, revision.lastIndexOf(".")); //$NON-NLS-1$
		if (branchNumber.lastIndexOf(".") == -1 || branchNumber.equals(CVSTag.VENDOR_REVISION)) { //$NON-NLS-1$
			return branchNumber;
		}
		String branchPrefix = branchNumber.substring(0,
				branchNumber.lastIndexOf(".")); //$NON-NLS-1$
		branchPrefix += ".0"; //$NON-NLS-1$
		branchPrefix += branchNumber.substring(branchNumber.lastIndexOf(".")); //$NON-NLS-1$
		return branchPrefix;
	}
	
	protected void beginFile(ICVSRepositoryLocation location, String fileName) {
		currentFile = RemoteFile.create(fileName, location);
		versions.clear();
	}

	protected void addEntry(LogEntry entry) {
		listener.handleLogEntryReceived(entry);
	}

	protected void handleInvalidFileName(ICVSRepositoryLocation location, String badFilePath) {
		CVSProviderPlugin.log(IStatus.WARNING, "Invalid file path '" + badFilePath + "' received from " + location.toString(), null); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Converts a time stamp as sent from a cvs server for a "log" command into a
	 * <code>Date</code>.
	 */
	private Date convertFromLogTime(String modTime) {
		DateFormat format = LOG_DATE_FORMATTER;
		// Compatibility for older cvs version (pre 1.12.9)
		if (modTime.length() > 4 && modTime.charAt(4) == '/')
			format = LOG_DATE_FORMATTER_OLD;
		
		try {
			return format.parse(modTime);
		} catch (ParseException e) {
			// fallback is to return null
			return null;
		}
	}
	
	private String internAndCopyString(String string) {
		String internedString = (String) internedStrings.get(string);
		if (internedString == null) {
			internedString = new String(string);
			internedStrings.put(internedString, internedString);
		}
		return internedString;
	}
	
	private String internString(String string) {
		String internedString = (String) internedStrings.get(string);
		if (internedString == null) {
			internedString = string;
			internedStrings.put(internedString, internedString);
		}
		return internedString;    	
	}
	
	private static class VersionInfo {
		private final boolean isBranch;
		private String tagRevision;
		private String branchRevision;
		private final String tagName;
		
		public VersionInfo(String version, String tagName) {
			this.tagName = tagName;
			this.isBranch = isBranchTag(version);
			tagRevision = version;
			if (isBranch) {
				int lastDot = version.lastIndexOf('.');
				if (lastDot == -1) {
					CVSProviderPlugin.log(IStatus.ERROR, 
						NLS.bind(CVSMessages.LogListener_invalidRevisionFormat, new String[] { tagName, version }), null); 
				} else {
					if (version.charAt(lastDot - 1) == '0' && version.charAt(lastDot - 2) == '.') {
						lastDot = lastDot - 2;
					}
					this.branchRevision = version;
					tagRevision = version.substring(0, lastDot);
				}
			}
		}

		public String getTagName() {
			return this.tagName;
		}
		
		public String getTagRevision() {
			return this.tagRevision;
		}
		
		public boolean isBranch() {
			return isBranch;
		}
		
		/** branch tags have odd number of segments or have
		 *  an even number with a zero as the second last segment
		 *  e.g: 1.1.1, 1.26.0.2 are branch revision numbers */
		private boolean isBranchTag(String tagName) {
			// First check if we have an odd number of segments (i.e. even number of dots)
			int numberOfDots = 0;
			int lastDot = 0;
			for (int i = 0; i < tagName.length(); i++) {
				if (tagName.charAt(i) == '.') {
					numberOfDots++;
					lastDot = i;
				}
			}
			if ((numberOfDots % 2) == 0) return true;
			if (numberOfDots == 1) return false;
			
			// If not, check if the second lat segment is a zero
			if (tagName.charAt(lastDot - 1) == '0' && tagName.charAt(lastDot - 2) == '.') return true;
			return false;
		}

		public String getBranchRevision() {
			return branchRevision;
		}
	}
}
