/*******************************************************************************
 * Copyright (c) 2004, 2016 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
 *     Martin Oberhuber (Wind River) - [276255] fix insertion of extra space chars
 *     Leo Ufimtsev lufimtse@redhat.com - [369991] Major re-write to handle multiple years. + added test cases.
 *******************************************************************************/
package org.eclipse.releng.tools;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.releng.tools.preferences.RelEngCopyrightConstants;

/**
 * <h2>Handle incomming 'raw' comments and convert them <br>
 * into a comment format with access to creation/revision year. <br>
 * When retrieving the comment, update the revision year or append one if it's not there.</h2>
 *
 * <p>
 * Tested in {@link org.eclipse.releng.tests.AdvancedCopyrightCommentTestsJunit4}<br>
 * Please verify that tests run after modifications.
 * </p>
 *
 */
public class AdvancedCopyrightComment extends CopyrightComment {

	/** A regex mattern to match years in the range {@code 19** to 23** } */
	private static final String YEAR_REGEX = "(19|20|21|22|23)\\d{2}"; //$NON-NLS-1$

	private static final String DATE_VAR = "${date}"; //$NON-NLS-1$
	private static final String NEW_LINE = "\n"; //$NON-NLS-1$

	/** Everything before the line with the year(s) on it. */
	private String preYearLinesString = null;

	/** The line with the year(s) on it. */
	private String yearLineString = null; // this is updated when we return a comment.

	/** Everything after the line with the year(s) on it. */
	private String postYearLineString = null;

	/** Number of year units matching {@link #YEAR_REGEX YEAR_REGEX} in the comment. e.g '2000, 2011-2014' has 3 */
	private int yearsCount;

	/**
	 * Return the body of this copyright comment or null if it cannot be built.
	 */
	@Override
	public String getCopyrightComment() {

		if ((preYearLinesString != null || postYearLineString != null)) {
			StringBuilder copyrightComment = new StringBuilder();

			// Pre-append everything before the years
			if (preYearLinesString != null) {
				copyrightComment.append(preYearLinesString);
			}

			// Check if the comment has a revised year. Fix the years on the line if so.
			if (hasRevisionYear() && (getRevisionYear() != getCreationYear())) {

				String fixedYearLine;
				if (yearsCount == 1) {
					// Insert a 2nd year '2000' -> '2000-2010'.
					fixedYearLine = insertRevisedYear(yearLineString, getRevisionYear());
				} else {
					// update the last found year on line: '2000 ... 2005' -> '2000 ... 2015'
					fixedYearLine = updateLastYear(yearLineString, getRevisionYear());
					if (fixedYearLine == null) {
						return null; //failed to update last year.
					}
				}

				copyrightComment.append(fixedYearLine);
			} else {
				// Otherwise put back the original year line.
				copyrightComment.append(yearLineString);
			}

			// Post append everything after the year line
			copyrightComment.append(postYearLineString);

			return copyrightComment.toString();
		}

		String linePrefix = getCommentPrefix();
		if (linePrefix == null)
			return null;

		StringWriter out = new StringWriter();
		
		try (PrintWriter writer = new PrintWriter(out)) {
			writeCommentStart(writer);
			writeLegal(writer, linePrefix);
			writeCommentEnd(writer);
			return out.toString();
		}
	}

	/**
	 * <h1>Parse a raw comment.</h1>
	 * <p>
	 * Create an instance the same as the argument comment but with the revision year <br>
	 * updated if needed. Return the default comment if the argument comment is null <br>
	 * or an empty string.
	 * </p>
	 *
	 * @param comment
	 *            the original comment from the file.
	 * @param commentStyle
	 *            the comment style. {@link CopyrightComment}
	 * @return {@link AdvancedCopyrightComment} an copyright comment with the year updated.
	 *
	 */
	public static AdvancedCopyrightComment parse(BlockComment commentBock, int commentStyle) {
		// If the given comment is empty, return the default comment.
		if (commentBock == null) {
			return defaultComment(commentStyle);
		}

		String comment = commentBock.getContents();

		// identify which line delimiter is used. (for writing back to file )
		String fileLineDelimiter = TextUtilities.determineLineDelimiter(comment, "\n"); //$NON-NLS-1$

		// Split Comment into Seperate lines for easier proccessing:
		String commentLines[] = comment.split("\\r?\\n"); //$NON-NLS-1$

		// lines before the line with the year comment on it.
		StringBuilder preYearLines = new StringBuilder();

		// line with the year(s) on it. 'copyright 2002, 2010-2011 ... etc..
		String yearLine = null;

		// Lines after the line with the year comment on it.
		StringBuilder postYearLines = new StringBuilder();

		// Break down the comment into the three sections.
		boolean yearFound = false;
		String line;
		for (int i = 0; i < commentLines.length; i++) {

			line = commentLines[i]; // for clarity.

			if (yearFound) {
				// We have already found the year line and are just appending the last lines.

				// Conditionally append a newline delimiter.
				if (i != (commentLines.length - 1)) {
					// normally, append a new line.
					postYearLines.append(line + fileLineDelimiter);
				} else {
					// for the last line, only append if the original comment had a newline delimiter.
					Character lastchar = comment.charAt(comment.length() - 1);
					if (Character.isWhitespace(lastchar)) {
						postYearLines.append(line + lastchar);
					} else {
						postYearLines.append(line);
					}
				}

			} else if (line.matches(".*" + YEAR_REGEX + ".*")) { //$NON-NLS-1$ //$NON-NLS-2$
				// We found the line with the copy-right years on it.
				yearFound = true;
				yearLine = line + fileLineDelimiter;
			} else {
				// We are parsting the top part of the comment and have not reached the year-line yet.
				preYearLines.append(line + fileLineDelimiter);
			}
		}

		// The comment didn't contain any years that we can update.
		if (!yearFound) {
			return null;
		}

		// Determine first year.
		int createdYear = getFirstYear(yearLine);
		if (createdYear == 0) {
			return null; //Failed to read a year.
		}


		int yearsOnLine = countYearsOnLine(yearLine);
		// Determine the last year
		int revisedYear;
		if (yearsOnLine == 1) {
			revisedYear = -1;
		} else {
			revisedYear = getLastYear(yearLine);
		}

		return new AdvancedCopyrightComment(commentStyle, createdYear, revisedYear, yearsOnLine,
				preYearLines.toString(), yearLine, postYearLines.toString());
	}

	/**
	 * <p> Construct a new default comment for the file.</p>
	 *
	 * @param commentStyle            As defined in: CopyrightComment
	 * @return                        a newly created comment.
	 */
	public static AdvancedCopyrightComment defaultComment(int commentStyle) {
		return new AdvancedCopyrightComment(commentStyle, -1, -1, 1, null, null, null);
	}


	private AdvancedCopyrightComment(int commentStyle, int creationYear, int revisionYear,
			int yearsCount, String preYearComment, String middleYearsComment, String postYearComment) {
		super(commentStyle, creationYear == -1 ? getPreferenceStore().getInt(
				RelEngCopyrightConstants.CREATION_YEAR_KEY) : creationYear, revisionYear);
		this.preYearLinesString = preYearComment;
		this.yearLineString = middleYearsComment;
		this.postYearLineString = postYearComment;
		this.yearsCount = yearsCount;
	}

	/**
	 * Get the copyright tool preference store.
	 *
	 * @return preference store used the releng plugin.
	 */
	private static IPreferenceStore getPreferenceStore() {
		return RelEngPlugin.getDefault().getPreferenceStore();
	}

	/**
	 * Get the copyright statement in form of an array of Strings where
	 * each item is a line of the copyright statement.
	 *
	 * @return String[]  array of lines making up the comment. Containing $date template.
	 */
	private static String[] getLegalLines() {
		StringTokenizer st = new StringTokenizer(getPreferenceStore().getString(
				RelEngCopyrightConstants.COPYRIGHT_TEMPLATE_KEY), NEW_LINE, true);
		ArrayList<String> lines = new ArrayList<>();
		String previous = NEW_LINE;
		while (st.hasMoreTokens()) {
			String current = st.nextToken();
			// add empty lines to array as well
			if (NEW_LINE.equals(previous)) {
				lines.add(current);
			}
			previous = current;
		}
		String[] stringLines = new String[lines.size()];
		stringLines = lines.toArray(stringLines);
		return stringLines;
	}

	/**
	 * Write out the copyright statement, line by line, adding in the created/revision
	 * year as well as comment line prefixes.
	 *
	 * @param writer
	 * @param linePrefix
	 */
	private void writeLegal(PrintWriter writer, String linePrefix) {
		String[] legalLines = getLegalLines();
		for (String currentLine : legalLines) {
			int offset = currentLine.indexOf(DATE_VAR);
			// if this is the line, containing the ${date}, add in the year
			if (offset > -1) {
				writer.print(linePrefix + ' ' + currentLine.substring(0, offset)
						+ getCreationYear());
				if (hasRevisionYear() && getRevisionYear() != getCreationYear()) {
					writer.print(", " + getRevisionYear()); //$NON-NLS-1$
				}
				println(writer,
						currentLine.substring(offset + DATE_VAR.length(), currentLine.length()));
			} else {
				// just write out the line
				if (NEW_LINE.equals(currentLine)) {
					// handle empty lines
					println(writer, linePrefix);
				} else {
					println(writer, linePrefix + ' ' + currentLine);
				}
			}
		}
	}

	/**
	 * Replace the last year in the provided string that matches {@link #YEAR_REGEX}.
	 *
	 * @param line
	 *            the line that contains the year that you want to update.
	 * @param newYear
	 *            the new year that you want to update to.
	 * @return    the string with the last year updated or null if it fails to find a year.
	 */
	private static String updateLastYear(String line, int newYear) {

		Matcher matcher = Pattern.compile(YEAR_REGEX).matcher(line);

		// Find position of last year in the string.
		int lastStart = -1;
		while (matcher.find()) {
			lastStart = matcher.start();
		}

		// Failed to find a year. Return the original line.
		if (lastStart == -1) {
			return null;
		}

		// Insert new year
		String before = line.substring(0, lastStart);
		String after = line.substring(lastStart + 4);
		String updatedLine = before + Integer.toString(newYear) + after;

		return updatedLine;
	}

	/**
	 * In the situation that a line only has a single year 'Copyright 2000 IBM ... '. <br>
	 * append the revision year to make it like: 'Copyright 2000-2010 IBM ... '. <br>
	 *
	 * <p>
	 * This should <b>only</b> be used for lines that have a single year.
	 * </p>
	 *
	 * @param line
	 * @param year
	 * @return
	 */
	private static String insertRevisedYear(String line, int year) {
		Matcher matcher = Pattern.compile(YEAR_REGEX).matcher(line);

		if (!matcher.find())
			return line; // no year found. Return original.

		// Insert new year.
		String before = line.substring(0, matcher.end());
		String after = line.substring(matcher.end());
		String updatedLine = before + ", " + Integer.toString(year) + after; //$NON-NLS-1$

		return updatedLine;
	}

	/**
	 * Given a line with one or multiple years on it, count how many years occur on it.
	 *
	 * @param line
	 * @return
	 */
	private static int countYearsOnLine(String line) {
		Matcher yearMatcher = Pattern.compile(YEAR_REGEX).matcher(line);
		int count = 0;
		while (yearMatcher.find()) {
			count++;
		}
		return count;
	}

	/**
	 * <h1>Get first year in line. </h1>
	 * <p> For example given a line like '2000, 2012, 2011, IMB..' it would return 2000. <br>
	 *
	 * Pre-condition: The line must contain a valid year in the range YEAR_REGEX
	 *
	 * @see #YEAR_REGEX
	 * @param line       Line containing a year.
	 * @return           the first found year. 0 if none found. (caller should check).
	 */
	private static int getFirstYear(String line) {
		Matcher yearMatcher = Pattern.compile(YEAR_REGEX).matcher(line);
		if (yearMatcher.find()) {
			return Integer.parseInt(yearMatcher.group()); // exception never thrown since match only matches integer.
		}
		return 0; //No year was found on this line.
	}

	/**
	 * <h2>Get the last year in a line. '2000, 2012, 2011, IMB..'</h2> Pre-condition: The line must contain a valid year
	 * in the range YEAR_REGEX
	 *
	 * @see #YEAR_REGEX
	 * @param line
	 * @return e.g 2011
	 */
	private static int getLastYear(String line) {
		Matcher yearMatcher = Pattern.compile(YEAR_REGEX).matcher(line);

		int lastYear = -1;
		// loop till the last occurance.
		while (yearMatcher.find()) {
			lastYear = Integer.parseInt(yearMatcher.group()); // exception never thrown since match only matches
															  // integer.
		}
		return lastYear;
	}
}
