/*
 * Copyright 2012 gitblit.com.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.gitblit.utils;

import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.compress.compressors.CompressorException;
import org.apache.commons.compress.compressors.CompressorStreamFactory;
import org.apache.commons.io.IOUtils;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.MutableObjectId;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.PathFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gitblit.GitBlit;
import com.gitblit.manager.IFilestoreManager;
import com.gitblit.models.FilestoreModel;
import com.gitblit.models.FilestoreModel.Status;

/**
 * Collection of static methods for retrieving information from a repository.
 *
 * @author James Moger
 *
 */
public class CompressionUtils {

	static final Logger LOGGER = LoggerFactory.getLogger(CompressionUtils.class);

	/**
	 * Log an error message and exception.
	 *
	 * @param t
	 * @param repository
	 *            if repository is not null it MUST be the {0} parameter in the
	 *            pattern.
	 * @param pattern
	 * @param objects
	 */
	private static void error(Throwable t, Repository repository, String pattern, Object... objects) {
		List<Object> parameters = new ArrayList<Object>();
		if (objects != null && objects.length > 0) {
			for (Object o : objects) {
				parameters.add(o);
			}
		}
		if (repository != null) {
			parameters.add(0, repository.getDirectory().getAbsolutePath());
		}
		LOGGER.error(MessageFormat.format(pattern, parameters.toArray()), t);
	}

	/**
	 * Zips the contents of the tree at the (optionally) specified revision and
	 * the (optionally) specified basepath to the supplied outputstream.
	 *
	 * @param repository
	 * @param basePath
	 *            if unspecified, entire repository is assumed.
	 * @param objectId
	 *            if unspecified, HEAD is assumed.
	 * @param os
	 * @return true if repository was successfully zipped to supplied output
	 *         stream
	 */
	public static boolean zip(Repository repository, IFilestoreManager filestoreManager, String basePath, String objectId,
			OutputStream os) {
		RevCommit commit = JGitUtils.getCommit(repository, objectId);
		if (commit == null) {
			return false;
		}
		boolean success = false;
		RevWalk rw = new RevWalk(repository);
		TreeWalk tw = new TreeWalk(repository);
		try {
			tw.reset();
			tw.addTree(commit.getTree());
			ZipArchiveOutputStream zos = new ZipArchiveOutputStream(os);
			zos.setComment("Generated by Gitblit");
			if (!StringUtils.isEmpty(basePath)) {
				PathFilter f = PathFilter.create(basePath);
				tw.setFilter(f);
			}
			tw.setRecursive(true);
			MutableObjectId id = new MutableObjectId();
			ObjectReader reader = tw.getObjectReader();
			long modified = commit.getAuthorIdent().getWhen().getTime();
			while (tw.next()) {
				FileMode mode = tw.getFileMode(0);
				if (mode == FileMode.GITLINK || mode == FileMode.TREE) {
					continue;
				}
				tw.getObjectId(id, 0);
				
				ObjectLoader loader = repository.open(id);
				
				ZipArchiveEntry entry = new ZipArchiveEntry(tw.getPathString());

				FilestoreModel filestoreItem = null;
				
				if (JGitUtils.isPossibleFilestoreItem(loader.getSize())) {
					filestoreItem = JGitUtils.getFilestoreItem(tw.getObjectReader().open(id));
				}

				final long size = (filestoreItem == null) ? loader.getSize() : filestoreItem.getSize();  

				entry.setSize(size);
				entry.setComment(commit.getName());
				entry.setUnixMode(mode.getBits());
				entry.setTime(modified);
				zos.putArchiveEntry(entry);
				
				if (filestoreItem == null) {
					//Copy repository stored file
					loader.copyTo(zos);
				} else {
					//Copy filestore file
					try (FileInputStream streamIn = new FileInputStream(filestoreManager.getStoragePath(filestoreItem.oid))) {
						IOUtils.copyLarge(streamIn, zos);
					} catch (Throwable e) {
						LOGGER.error(MessageFormat.format("Failed to archive filestore item {0}", filestoreItem.oid), e);

						//Handle as per other errors 
						throw e; 
					}
				}

				zos.closeArchiveEntry();
			}
			zos.finish();
			success = true;
		} catch (IOException e) {
			error(e, repository, "{0} failed to zip files from commit {1}", commit.getName());
		} finally {
			tw.close();
			rw.dispose();
		}
		return success;
	}

	/**
	 * tar the contents of the tree at the (optionally) specified revision and
	 * the (optionally) specified basepath to the supplied outputstream.
	 *
	 * @param repository
	 * @param basePath
	 *            if unspecified, entire repository is assumed.
	 * @param objectId
	 *            if unspecified, HEAD is assumed.
	 * @param os
	 * @return true if repository was successfully zipped to supplied output
	 *         stream
	 */
	public static boolean tar(Repository repository, IFilestoreManager filestoreManager, String basePath, String objectId,
			OutputStream os) {
		return tar(null, repository, filestoreManager, basePath, objectId, os);
	}

	/**
	 * tar.gz the contents of the tree at the (optionally) specified revision and
	 * the (optionally) specified basepath to the supplied outputstream.
	 *
	 * @param repository
	 * @param basePath
	 *            if unspecified, entire repository is assumed.
	 * @param objectId
	 *            if unspecified, HEAD is assumed.
	 * @param os
	 * @return true if repository was successfully zipped to supplied output
	 *         stream
	 */
	public static boolean gz(Repository repository, IFilestoreManager filestoreManager, String basePath, String objectId,
			OutputStream os) {
		return tar(CompressorStreamFactory.GZIP, repository, filestoreManager, basePath, objectId, os);
	}

	/**
	 * tar.xz the contents of the tree at the (optionally) specified revision and
	 * the (optionally) specified basepath to the supplied outputstream.
	 *
	 * @param repository
	 * @param basePath
	 *            if unspecified, entire repository is assumed.
	 * @param objectId
	 *            if unspecified, HEAD is assumed.
	 * @param os
	 * @return true if repository was successfully zipped to supplied output
	 *         stream
	 */
	public static boolean xz(Repository repository, IFilestoreManager filestoreManager, String basePath, String objectId,
			OutputStream os) {
		return tar(CompressorStreamFactory.XZ, repository, filestoreManager, basePath, objectId, os);
	}

	/**
	 * tar.bzip2 the contents of the tree at the (optionally) specified revision and
	 * the (optionally) specified basepath to the supplied outputstream.
	 *
	 * @param repository
	 * @param basePath
	 *            if unspecified, entire repository is assumed.
	 * @param objectId
	 *            if unspecified, HEAD is assumed.
	 * @param os
	 * @return true if repository was successfully zipped to supplied output
	 *         stream
	 */
	public static boolean bzip2(Repository repository, IFilestoreManager filestoreManager, String basePath, String objectId,
			OutputStream os) {

		return tar(CompressorStreamFactory.BZIP2, repository, filestoreManager, basePath, objectId, os);
	}

	/**
	 * Compresses/archives the contents of the tree at the (optionally)
	 * specified revision and the (optionally) specified basepath to the
	 * supplied outputstream.
	 *
	 * @param algorithm
	 *            compression algorithm for tar (optional)
	 * @param repository
	 * @param basePath
	 *            if unspecified, entire repository is assumed.
	 * @param objectId
	 *            if unspecified, HEAD is assumed.
	 * @param os
	 * @return true if repository was successfully zipped to supplied output
	 *         stream
	 */
	private static boolean tar(String algorithm, Repository repository, IFilestoreManager filestoreManager, String basePath, String objectId,
			OutputStream os) {
		RevCommit commit = JGitUtils.getCommit(repository, objectId);
		if (commit == null) {
			return false;
		}

		OutputStream cos = os;
		if (!StringUtils.isEmpty(algorithm)) {
			try {
				cos = new CompressorStreamFactory().createCompressorOutputStream(algorithm, os);
			} catch (CompressorException e1) {
				error(e1, repository, "{0} failed to open {1} stream", algorithm);
			}
		}
		boolean success = false;
		RevWalk rw = new RevWalk(repository);
		TreeWalk tw = new TreeWalk(repository);
		try {
			tw.reset();
			tw.addTree(commit.getTree());
			TarArchiveOutputStream tos = new TarArchiveOutputStream(cos);
			tos.setAddPaxHeadersForNonAsciiNames(true);
			tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
			if (!StringUtils.isEmpty(basePath)) {
				PathFilter f = PathFilter.create(basePath);
				tw.setFilter(f);
			}
			tw.setRecursive(true);
			MutableObjectId id = new MutableObjectId();
			long modified = commit.getAuthorIdent().getWhen().getTime();
			while (tw.next()) {
				FileMode mode = tw.getFileMode(0);
				if (mode == FileMode.GITLINK || mode == FileMode.TREE) {
					continue;
				}
				
				tw.getObjectId(id, 0);

				ObjectLoader loader = repository.open(id);
				if (FileMode.SYMLINK == mode) {
					TarArchiveEntry entry = new TarArchiveEntry(tw.getPathString(),TarArchiveEntry.LF_SYMLINK);
					ByteArrayOutputStream bos = new ByteArrayOutputStream();
					loader.copyTo(bos);
					entry.setLinkName(bos.toString());
					entry.setModTime(modified);
					tos.putArchiveEntry(entry);
					tos.closeArchiveEntry();
				} else {
					TarArchiveEntry entry = new TarArchiveEntry(tw.getPathString());
					entry.setMode(mode.getBits());
					entry.setModTime(modified);

					FilestoreModel filestoreItem = null;
					
					if (JGitUtils.isPossibleFilestoreItem(loader.getSize())) {
						filestoreItem = JGitUtils.getFilestoreItem(tw.getObjectReader().open(id));
					}

					final long size = (filestoreItem == null) ? loader.getSize() : filestoreItem.getSize();  

					entry.setSize(size);
					tos.putArchiveEntry(entry);
					
					if (filestoreItem == null) {
						//Copy repository stored file
						loader.copyTo(tos);
					} else {
						//Copy filestore file
						try (FileInputStream streamIn = new FileInputStream(filestoreManager.getStoragePath(filestoreItem.oid))) {

							IOUtils.copyLarge(streamIn, tos);
						} catch (Throwable e) {
							LOGGER.error(MessageFormat.format("Failed to archive filestore item {0}", filestoreItem.oid), e);

							//Handle as per other errors 
							throw e; 
						}
					}
					
					tos.closeArchiveEntry();
				}
			}
			tos.finish();
			tos.close();
			cos.close();
			success = true;
		} catch (IOException e) {
			error(e, repository, "{0} failed to {1} stream files from commit {2}", algorithm, commit.getName());
		} finally {
			tw.close();
			rw.dispose();
		}
		return success;
	}
}
