/*******************************************************************************
 * Copyright (c) 2007 IBM Corporation and others.
 * 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
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.equinox.internal.p2.touchpoint.natives;

import java.io.*;
import java.net.URL;
import java.util.*;
import java.util.zip.*;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.equinox.internal.p2.core.helpers.FileUtils;
import org.eclipse.osgi.util.NLS;

public class BackupFiles {

	private static final String ZIP_SUFFIX = ".zip"; //$NON-NLS-1$
	private static final String PROPERTIES_SUFFIX = ".properties"; //$NON-NLS-1$

	private final File backupDir;
	private boolean doBackup;

	/**
	 * Save or restore backups of files in backupDir
	 */
	public BackupFiles(File backupDir) {
		this.doBackup = true;
		this.backupDir = backupDir;
		this.backupDir.mkdirs();
	}

	//    /**
	//     * If doBackup is set to false, files are deleted on uninstall, instead of restored.
	//     */
	//    public void setDoBackup(boolean doBackup) {
	//        this.doBackup = doBackup;
	//    }

	/**
	 * Restore all backups made in this dir.
	 */
	public void restore(IProgressMonitor monitor) throws IOException {
		// find backup properties files, do in reverse order
		List propsFiles = new LinkedList();
		for (int i = 0;; i += 1) {
			File propsFile = getBackupProperties(i);
			if (!propsFile.exists()) {
				break;
			}
			propsFiles.add(0, propsFile);
		}
		IProgressMonitor[] pm = Util.splitProgressMonitor(monitor, propsFiles.size());
		int j = 0;
		for (Iterator i = propsFiles.iterator(); i.hasNext();) {
			File propsFile = (File) i.next();
			restoreFilesFromBackup(propsFile, pm[j++]);
		}
		if (!this.backupDir.delete()) {
			//not empty?  log a warning?
		} else {
			// delete the parent if empty
			this.backupDir.getParentFile().delete();
		}
		monitor.done();
	}

	/**
	 * Find files under outputDir that will be overwritten in unzipURL
	 * and save under backupDir, and delete.
	 * Include properties file to indicate files to delete or restore on rolled back.
	 * The progress monitor is used only to display sub-tasks; we don't update it otherwise.
	 */
	public void backupFilesInZip(String identifier, URL zipURL, File outputDir, IProgressMonitor monitor) throws IOException {
		BackupProperties backupProps = new BackupProperties(identifier, outputDir);
		ZipOutputStream zos = null;
		String prevDir = null;
		try {
			ZipInputStream in = new ZipInputStream(zipURL.openStream());
			ZipEntry ze;
			while ((ze = in.getNextEntry()) != null) {
				String name = ze.getName();
				int i = name.lastIndexOf('/');
				if (i != -1) {
					String dir = name.substring(0, i);
					if (this.doBackup && !dir.equals(prevDir)) {
						monitor.subTask(name.substring(0, i));
						prevDir = dir;
					}
				}
				if (!ze.isDirectory()) {
					File origFile = new File(outputDir, name);
					if (this.doBackup && origFile.exists()) {
						if (zos == null) {
							File zipFile = backupProps.getArchive();
							zos = new ZipOutputStream(new FileOutputStream(zipFile));
						}
						ZipEntry zipEntry = new ZipEntry(name);
						zipEntry.setTime(origFile.lastModified());
						zos.putNextEntry(zipEntry);
						FileUtils.copyStream(new FileInputStream(origFile), true, zos, false);
						zos.closeEntry();
					} else {
						backupProps.addFileToDelete(name);
					}
					origFile.delete();
				}
				in.closeEntry();
			}
			in.close();
		} finally {
			backupProps.store();
			if (zos != null) {
				zos.close();
			}
		}
	}

	private void restoreFilesFromBackup(File propsFile, IProgressMonitor monitor) throws IOException {
		BackupProperties backupProps = new BackupProperties(propsFile);
		monitor.beginTask(NLS.bind(Messages.restoring, propsFile.toString()), 3);
		monitor.subTask(""); //$NON-NLS-1$
		for (Iterator i = backupProps.getFilesToDelete().iterator(); i.hasNext();) {
			String name = (String) i.next();
			File full = new File(backupProps.getRootDir(), name);
			full.delete();
		}
		monitor.worked(1);
		File zipFile = backupProps.getArchive();
		if (zipFile.exists()) { // only exists if files were saved
			SubProgressMonitor sub = new SubProgressMonitor(monitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
			FileUtils.unzipFile(zipFile, backupProps.getRootDir(), "", sub); //$NON-NLS-1$
			zipFile.delete();
		} else {
			monitor.worked(1);
		}
		for (Iterator i = backupProps.getDirsToDelete().iterator(); i.hasNext();) {
			String name = (String) i.next();
			File full = new File(backupProps.getRootDir(), name);
			FileUtils.deleteEmptyDirs(full);
		}
		propsFile.delete();
		monitor.worked(1);
		monitor.done();
	}

	// Backup files are just 0.properties, 1.properties, etc.
	// Get the next unused one.
	File getBackupProperties() {
		for (int i = 0;; i += 1) {
			File result = getBackupProperties(i);
			if (!result.exists())
				return result;
		}
	}

	private File getBackupProperties(int i) {
		return new File(BackupFiles.this.backupDir, Integer.toString(i) + PROPERTIES_SUFFIX);
	}

	private class BackupProperties extends Properties {
		private static final long serialVersionUID = 2268313492348533029L;
		private static final char FILE_KIND = 'f';
		private static final char DIR_KIND = 'd';
		private static final String ROOT_DIR = "rootDir"; //$NON-NLS-1$
		private static final String ARTIFACT_KEY = "artifactKey"; //$NON-NLS-1$
		//		private static final String ARTIFACT_USER = "artifactUser"; //$NON-NLS-1$

		private int n = 0; // number of properties
		private File file; // file to store properties in
		private List keys = new LinkedList(); // keys, in order they were added or read
		private final File rootDir; // root of where files are going
		private Set dirsToCreate = new TreeSet(); // set of dirs we will create

		// create properties based on file we are backing up to
		public BackupProperties(String identifier, File rootDir) {
			this.file = BackupFiles.this.getBackupProperties();
			this.rootDir = rootDir;
			setProperty(ROOT_DIR, rootDir.getPath().replace('\\', '/'));
			setProperty(ARTIFACT_KEY, (identifier != null ? identifier : rootDir.getAbsolutePath()));
			//			setProperty(ARTIFACT_USER, artifact.toUserString());
			// make sure rootDir is deleted if appropriate
			addDir("./"); //$NON-NLS-1$
		}

		// create backup properties from a previously saved BackupProperties
		public BackupProperties(File file) throws IOException {
			this.file = file;
			FileInputStream stream = new FileInputStream(file);
			try {
				load(stream);
			} finally {
				stream.close();
			}
			this.rootDir = new File(getProperty(ROOT_DIR));
		}

		//		public String getArtifactKey() {
		//			return getProperty(ARTIFACT_KEY);
		//		}

		//		public String getArtifactUserString() {
		//			String result = getProperty(ARTIFACT_USER);
		//			if (result != null) {
		//				return result;
		//			} else {
		//				// return something if the key wasn't saved
		//				result = getArtifactKey();
		//				result = result.replaceFirst(",native,", ","); //$NON-NLS-1$ //$NON-NLS-2$
		//				return result.replace(',', ' ').trim();
		//			}
		//		}

		public File getRootDir() {
			return this.rootDir;
		}

		// We are backing up files for this artifact.
		// Create a backup zip based on the artifact key (as a hint).
		public File getArchive() {
			String path = this.file.getPath();
			if (path.endsWith(PROPERTIES_SUFFIX)) {
				path = path.substring(0, path.length() - PROPERTIES_SUFFIX.length());
			}
			return new File(path + ZIP_SUFFIX);
		}

		public List getFilesToDelete() {
			return getMatchingProperties(FILE_KIND);
		}

		public List getDirsToDelete() {
			return getMatchingProperties(DIR_KIND);
		}

		private List getMatchingProperties(char c) {
			List result = new LinkedList();
			for (Enumeration e = propertyNames(); e.hasMoreElements();) {
				String key = (String) e.nextElement();
				if (key.equals(BackupProperties.ROOT_DIR)) {
					continue;
				}
				if (key.charAt(0) == c) {
					result.add(getProperty(key));
				}
			}
			return result;
		}

		public void addFileToDelete(String name) {
			add(FILE_KIND, name);
			addDir(name);
		}

		public void store() throws IOException {
			// add the directories -- at end because we want them all in order
			for (Iterator i = this.dirsToCreate.iterator(); i.hasNext();) {
				String name = (String) i.next();
				add(DIR_KIND, name);
			}
			FileOutputStream stream = new FileOutputStream(this.file);
			try {
				store(stream, /*header*/null);
			} finally {
				stream.close();
			}
		}

		public Object put(Object key, Object value) {
			if (!(key instanceof String))
				throw new AssertionError("expected String: " + key); //$NON-NLS-1$
			if (!(value instanceof String))
				throw new AssertionError("expected String: " + value); //$NON-NLS-1$
			this.keys.add(key);
			return super.put(key, value);
		}

		// return keys in the order they were added
		public synchronized Enumeration keys() {
			final Iterator iterator = this.keys.iterator();
			return new Enumeration() {
				public boolean hasMoreElements() {
					return iterator.hasNext();
				}

				public Object nextElement() {
					return iterator.next();
				}
			};
		}

		private void add(char kind, String name) {
			StringBuffer key = new StringBuffer(4);
			key.append(kind).append(n++);
			setProperty(key.toString(), name.replace('\\', '/'));
		}

		// if we're going to create this dir, remember that so we delete it
		private void addDir(String name) {
			int slash = name.lastIndexOf('/');
			if (slash == -1)
				return; // no dir
			String dirName = name.substring(0, slash);
			if (this.dirsToCreate.contains(dirName))
				return; // already have it
			if (new File(this.rootDir, dirName).exists())
				return; // already exists
			this.dirsToCreate.add(dirName);
		}

	}

}
