/*
 * Copyright (C) 2015, 2022 Ivan Motsch <ivan.motsch@bsiag.com> and others
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0 which is available at
 * https://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
package org.eclipse.jgit.attributes;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.function.Supplier;

import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.attributes.Attribute.State;
import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.treewalk.AbstractTreeIterator;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.TreeWalk.OperationType;
import org.eclipse.jgit.treewalk.WorkingTreeIterator;

/**
 * The attributes handler knows how to retrieve, parse and merge attributes from
 * the various gitattributes files. Furthermore it collects and expands macro
 * expressions. The method {@link #getAttributes()} yields the ready processed
 * attributes for the current path represented by the
 * {@link org.eclipse.jgit.treewalk.TreeWalk}
 * <p>
 * The implementation is based on the specifications in
 * http://git-scm.com/docs/gitattributes
 *
 * @since 4.3
 */
public class AttributesHandler {
	private static final String MACRO_PREFIX = "[attr]"; //$NON-NLS-1$

	private static final String BINARY_RULE_KEY = "binary"; //$NON-NLS-1$

	/**
	 * This is the default <b>binary</b> rule that is present in any git folder
	 * <code>[attr]binary -diff -merge -text</code>
	 */
	private static final List<Attribute> BINARY_RULE_ATTRIBUTES = new AttributesRule(
			MACRO_PREFIX + BINARY_RULE_KEY, "-diff -merge -text") //$NON-NLS-1$
					.getAttributes();

	private final TreeWalk treeWalk;

	private final Supplier<CanonicalTreeParser> attributesTree;

	private final AttributesNode globalNode;

	private final AttributesNode infoNode;

	private final Map<String, List<Attribute>> expansions = new HashMap<>();

	/**
	 * Create an {@link org.eclipse.jgit.attributes.AttributesHandler} with
	 * default rules as well as merged rules from global, info and worktree root
	 * attributes
	 *
	 * @param treeWalk
	 *            a {@link org.eclipse.jgit.treewalk.TreeWalk}
	 * @throws java.io.IOException
	 *             if an IO error occurred
	 * @deprecated since 6.1, use {@link #AttributesHandler(TreeWalk, Supplier)}
	 *             instead
	 */
	@Deprecated
	public AttributesHandler(TreeWalk treeWalk) throws IOException {
		this(treeWalk, () -> treeWalk.getTree(CanonicalTreeParser.class));
	}

	/**
	 * Create an {@link org.eclipse.jgit.attributes.AttributesHandler} with
	 * default rules as well as merged rules from global, info and worktree root
	 * attributes
	 *
	 * @param treeWalk
	 *            a {@link org.eclipse.jgit.treewalk.TreeWalk}
	 * @param attributesTree
	 *            the tree to read .gitattributes from
	 * @throws java.io.IOException
	 *             if an IO error occurred
	 * @since 6.1
	 */
	public AttributesHandler(TreeWalk treeWalk,
			Supplier<CanonicalTreeParser> attributesTree) throws IOException {
		this.treeWalk = treeWalk;
		this.attributesTree = attributesTree;
		AttributesNodeProvider attributesNodeProvider = treeWalk
				.getAttributesNodeProvider();
		this.globalNode = attributesNodeProvider != null
				? attributesNodeProvider.getGlobalAttributesNode() : null;
		this.infoNode = attributesNodeProvider != null
				? attributesNodeProvider.getInfoAttributesNode() : null;

		AttributesNode rootNode = attributesNode(treeWalk,
				rootOf(treeWalk.getTree(WorkingTreeIterator.class)),
				rootOf(treeWalk.getTree(DirCacheIterator.class)),
				rootOf(attributesTree.get()));

		expansions.put(BINARY_RULE_KEY, BINARY_RULE_ATTRIBUTES);
		for (AttributesNode node : new AttributesNode[] { globalNode, rootNode,
				infoNode }) {
			if (node == null) {
				continue;
			}
			for (AttributesRule rule : node.getRules()) {
				if (rule.getPattern().startsWith(MACRO_PREFIX)) {
					expansions.put(rule.getPattern()
							.substring(MACRO_PREFIX.length()).trim(),
							rule.getAttributes());
				}
			}
		}
	}

	/**
	 * See {@link org.eclipse.jgit.treewalk.TreeWalk#getAttributes()}
	 *
	 * @return the {@link org.eclipse.jgit.attributes.Attributes} for the
	 *         current path represented by the
	 *         {@link org.eclipse.jgit.treewalk.TreeWalk}
	 * @throws java.io.IOException
	 *             if an IO error occurred
	 */
	public Attributes getAttributes() throws IOException {
		String entryPath = treeWalk.getPathString();
		boolean isDirectory = (treeWalk.getFileMode() == FileMode.TREE);
		Attributes attributes = new Attributes();

		// Gets the info attributes
		mergeInfoAttributes(entryPath, isDirectory, attributes);

		// Gets the attributes located on the current entry path
		mergePerDirectoryEntryAttributes(entryPath, entryPath.lastIndexOf('/'),
				isDirectory,
				treeWalk.getTree(WorkingTreeIterator.class),
				treeWalk.getTree(DirCacheIterator.class),
				attributesTree.get(),
				attributes);

		// Gets the attributes located in the global attribute file
		mergeGlobalAttributes(entryPath, isDirectory, attributes);

		// now after all attributes are collected - in the correct hierarchy
		// order - remove all unspecified entries (the ! marker)
		for (Attribute a : attributes.getAll()) {
			if (a.getState() == State.UNSPECIFIED)
				attributes.remove(a.getKey());
		}

		return attributes;
	}

	/**
	 * Merges the matching GLOBAL attributes for an entry path.
	 *
	 * @param entryPath
	 *            the path to test. The path must be relative to this attribute
	 *            node's own repository path, and in repository path format
	 *            (uses '/' and not '\').
	 * @param isDirectory
	 *            true if the target item is a directory.
	 * @param result
	 *            that will hold the attributes matching this entry path. This
	 *            method will NOT override any existing entry in attributes.
	 */
	private void mergeGlobalAttributes(String entryPath, boolean isDirectory,
			Attributes result) {
		mergeAttributes(globalNode, entryPath, isDirectory, result);
	}

	/**
	 * Merges the matching INFO attributes for an entry path.
	 *
	 * @param entryPath
	 *            the path to test. The path must be relative to this attribute
	 *            node's own repository path, and in repository path format
	 *            (uses '/' and not '\').
	 * @param isDirectory
	 *            true if the target item is a directory.
	 * @param result
	 *            that will hold the attributes matching this entry path. This
	 *            method will NOT override any existing entry in attributes.
	 */
	private void mergeInfoAttributes(String entryPath, boolean isDirectory,
			Attributes result) {
		mergeAttributes(infoNode, entryPath, isDirectory, result);
	}

	/**
	 * Merges the matching working directory attributes for an entry path.
	 *
	 * @param entryPath
	 *            the path to test. The path must be relative to this attribute
	 *            node's own repository path, and in repository path format
	 *            (uses '/' and not '\').
	 * @param nameRoot
	 *            index of the '/' preceeding the current level, or -1 if none
	 * @param isDirectory
	 *            true if the target item is a directory.
	 * @param workingTreeIterator
	 *            the working tree iterator
	 * @param dirCacheIterator
	 *            the dircache iterator
	 * @param otherTree
	 *            another tree
	 * @param result
	 *            that will hold the attributes matching this entry path. This
	 *            method will NOT override any existing entry in attributes.
	 * @throws IOException
	 *             if an IO error occurred
	 */
	private void mergePerDirectoryEntryAttributes(String entryPath,
			int nameRoot, boolean isDirectory,
			@Nullable WorkingTreeIterator workingTreeIterator,
			@Nullable DirCacheIterator dirCacheIterator,
			@Nullable CanonicalTreeParser otherTree, Attributes result)
					throws IOException {
		// Prevents infinite recurrence
		if (workingTreeIterator != null || dirCacheIterator != null
				|| otherTree != null) {
			AttributesNode attributesNode = attributesNode(
					treeWalk, workingTreeIterator, dirCacheIterator, otherTree);
			if (attributesNode != null) {
				mergeAttributes(attributesNode,
						entryPath.substring(nameRoot + 1), isDirectory,
						result);
			}
			mergePerDirectoryEntryAttributes(entryPath,
					entryPath.lastIndexOf('/', nameRoot - 1), isDirectory,
					parentOf(workingTreeIterator), parentOf(dirCacheIterator),
					parentOf(otherTree), result);
		}
	}

	/**
	 * Merges the matching node attributes for an entry path.
	 *
	 * @param node
	 *            the node to scan for matches to entryPath
	 * @param entryPath
	 *            the path to test. The path must be relative to this attribute
	 *            node's own repository path, and in repository path format
	 *            (uses '/' and not '\').
	 * @param isDirectory
	 *            true if the target item is a directory.
	 * @param result
	 *            that will hold the attributes matching this entry path. This
	 *            method will NOT override any existing entry in attributes.
	 */
	protected void mergeAttributes(@Nullable AttributesNode node,
			String entryPath,
			boolean isDirectory, Attributes result) {
		if (node == null)
			return;
		List<AttributesRule> rules = node.getRules();
		// Parse rules in the reverse order that they were read since the last
		// entry should be used
		ListIterator<AttributesRule> ruleIterator = rules
				.listIterator(rules.size());
		while (ruleIterator.hasPrevious()) {
			AttributesRule rule = ruleIterator.previous();
			if (rule.isMatch(entryPath, isDirectory)) {
				ListIterator<Attribute> attributeIte = rule.getAttributes()
						.listIterator(rule.getAttributes().size());
				// Parses the attributes in the reverse order that they were
				// read since the last entry should be used
				while (attributeIte.hasPrevious()) {
					expandMacro(attributeIte.previous(), result);
				}
			}
		}
	}

	/**
	 * Expand a macro
	 *
	 * @param attr
	 *            a {@link org.eclipse.jgit.attributes.Attribute}
	 * @param result
	 *            contains the (recursive) expanded and merged macro attributes
	 *            including the attribute iself
	 */
	protected void expandMacro(Attribute attr, Attributes result) {
		// loop detection = exists check
		if (result.containsKey(attr.getKey()))
			return;

		// also add macro to result set, same does native git
		result.put(attr);

		List<Attribute> expansion = expansions.get(attr.getKey());
		if (expansion == null) {
			return;
		}
		switch (attr.getState()) {
		case UNSET: {
			for (Attribute e : expansion) {
				switch (e.getState()) {
				case SET:
					expandMacro(new Attribute(e.getKey(), State.UNSET), result);
					break;
				case UNSET:
					expandMacro(new Attribute(e.getKey(), State.SET), result);
					break;
				case UNSPECIFIED:
					expandMacro(new Attribute(e.getKey(), State.UNSPECIFIED),
							result);
					break;
				case CUSTOM:
				default:
					expandMacro(e, result);
				}
			}
			break;
		}
		case CUSTOM: {
			for (Attribute e : expansion) {
				switch (e.getState()) {
				case SET:
				case UNSET:
				case UNSPECIFIED:
					expandMacro(e, result);
					break;
				case CUSTOM:
				default:
					expandMacro(new Attribute(e.getKey(), attr.getValue()),
							result);
				}
			}
			break;
		}
		case UNSPECIFIED: {
			for (Attribute e : expansion) {
				expandMacro(new Attribute(e.getKey(), State.UNSPECIFIED),
						result);
			}
			break;
		}
		case SET:
		default:
			for (Attribute e : expansion) {
				expandMacro(e, result);
			}
			break;
		}
	}

	/**
	 * Get the {@link AttributesNode} for the current entry.
	 * <p>
	 * This method implements the fallback mechanism between the index and the
	 * working tree depending on the operation type
	 * </p>
	 *
	 * @param treeWalk
	 *            used to walk trees
	 * @param workingTreeIterator
	 *            used to walk the working tree
	 * @param dirCacheIterator
	 *            used to walk the dircache
	 * @param otherTree
	 *            another tree
	 * @return a {@link AttributesNode} of the current entry,
	 *         {@link NullPointerException} otherwise.
	 * @throws IOException
	 *             It raises an {@link IOException} if a problem appears while
	 *             parsing one on the attributes file.
	 */
	private static AttributesNode attributesNode(TreeWalk treeWalk,
			@Nullable WorkingTreeIterator workingTreeIterator,
			@Nullable DirCacheIterator dirCacheIterator,
			@Nullable CanonicalTreeParser otherTree) throws IOException {
		AttributesNode attributesNode = null;
		switch (treeWalk.getOperationType()) {
		case CHECKIN_OP:
			if (workingTreeIterator != null) {
				attributesNode = workingTreeIterator.getEntryAttributesNode();
			}
			if (attributesNode == null && dirCacheIterator != null) {
				attributesNode = dirCacheIterator
						.getEntryAttributesNode(treeWalk.getObjectReader());
			}
			if (attributesNode == null && otherTree != null) {
				attributesNode = otherTree
						.getEntryAttributesNode(treeWalk.getObjectReader());
			}
			break;
		case CHECKOUT_OP:
			if (otherTree != null) {
				attributesNode = otherTree
						.getEntryAttributesNode(treeWalk.getObjectReader());
			}
			if (attributesNode == null && dirCacheIterator != null) {
				attributesNode = dirCacheIterator
						.getEntryAttributesNode(treeWalk.getObjectReader());
			}
			if (attributesNode == null && workingTreeIterator != null) {
				attributesNode = workingTreeIterator.getEntryAttributesNode();
			}
			break;
		default:
			throw new IllegalStateException(
					"The only supported operation types are:" //$NON-NLS-1$
							+ OperationType.CHECKIN_OP + "," //$NON-NLS-1$
							+ OperationType.CHECKOUT_OP);
		}

		return attributesNode;
	}

	private static <T extends AbstractTreeIterator> T parentOf(@Nullable T node) {
		if(node==null) return null;
		@SuppressWarnings("unchecked")
		Class<T> type = (Class<T>) node.getClass();
		AbstractTreeIterator parent = node.parent;
		if (type.isInstance(parent)) {
			return type.cast(parent);
		}
		return null;
	}

	private static <T extends AbstractTreeIterator> T rootOf(
			@Nullable T node) {
		if(node==null) return null;
		AbstractTreeIterator t=node;
		while (t!= null && t.parent != null) {
			t= t.parent;
		}
		@SuppressWarnings("unchecked")
		Class<T> type = (Class<T>) node.getClass();
		if (type.isInstance(t)) {
			return type.cast(t);
		}
		return null;
	}

}
