/*******************************************************************************
 * Copyright (C) 2007, Robin Rosenberg <me@lathund.dewire.com>
 * Copyright (C) 2006, Robin Rosenberg <robin.rosenberg@dewire.com>
 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
 * Copyright (C) 2011, Dariusz Luksza <dariusz@luksza.org>
 * Copyright (C) 2013, Robin Stocker <robin@nibor.org>
 *
 * 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
 *******************************************************************************/
package org.eclipse.egit.core.internal.storage;

import java.io.IOException;

import org.eclipse.core.resources.IStorage;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.egit.core.Activator;
import org.eclipse.egit.core.internal.CoreText;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.osgi.util.NLS;
import org.eclipse.team.core.history.IFileRevision;

/** An {@link IFileRevision} for the version in the Git index. */
public class IndexFileRevision extends GitFileRevision {

	// This is to maintain compatibility with the old behavior
	private static final int FIRST_AVAILABLE = -1;

	private final Repository db;

	private final String path;

	private final int stage;

	private ObjectId blobId;

	IndexFileRevision(final Repository repo, final String path) {
		this(repo, path, FIRST_AVAILABLE);
	}

	IndexFileRevision(final Repository repo, final String path, int stage) {
		super(path);
		this.db = repo;
		this.path = path;
		this.stage = stage;
	}

	public IStorage getStorage(IProgressMonitor monitor) throws CoreException {
		if (blobId == null)
			blobId = locateBlobObjectId();
		return new IndexBlobStorage(db, path, blobId);
	}

	public boolean isPropertyMissing() {
		return false;
	}

	public String getAuthor() {
		return "";  //$NON-NLS-1$
	}

	public long getTimestamp() {
		return -1;
	}

	public String getComment() {
		return null;
	}

	public String getContentIdentifier() {
		return INDEX;
	}

	private ObjectId locateBlobObjectId() throws CoreException {
		try {
			DirCache dc = db.readDirCache();
			int firstIndex = dc.findEntry(path);
			if (firstIndex < 0)
				return null;

			// Try to avoid call to nextEntry if first entry already matches
			DirCacheEntry firstEntry = dc.getEntry(firstIndex);
			if (stage == FIRST_AVAILABLE || firstEntry.getStage() == stage)
				return firstEntry.getObjectId();

			// Ok, we have to search
			int nextIndex = dc.nextEntry(firstIndex);
			for (int i = firstIndex; i < nextIndex; i++) {
				DirCacheEntry entry = dc.getEntry(i);
				if (entry.getStage() == stage)
					return entry.getObjectId();
			}
			return null;
		} catch (IOException e) {
			throw new CoreException(Activator.error(NLS.bind(
					CoreText.IndexFileRevision_errorLookingUpPath, path), e));
		}
	}
}
