package net.oni2.aeinstaller.backend.oni.management.tools;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.TreeSet;

import net.oni2.aeinstaller.backend.CaseInsensitiveFile;
import net.oni2.aeinstaller.backend.FileChecksum;
import net.oni2.aeinstaller.backend.Paths;
import net.oni2.aeinstaller.backend.packages.Package;
import net.oni2.aeinstaller.backend.packages.PackageManager;

import org.apache.commons.io.FileUtils;

/**
 * @author Christian Illy
 */
public class ToolsManager {

	/**
	 * Verify integrity of installed tools
	 */
	public static void verifyToolsIntegrity() {
		final ToolInstallationList til = ToolInstallationList.getInstance();
		for (final Package m : PackageManager.getInstance().getInstalledTools()) {
			ToolFileIterator.iteratePlatformToolFiles(m,
					new ToolFileIteratorEntry() {
						@Override
						public void toolFile(File source, File target) {
							byte[] chkSrc = FileChecksum
									.calculateFileMD5(source);
							if (!target.exists()) {
								til.markModified(m.getPackageNumber(), true);
							} else {
								byte[] chkTrg = FileChecksum
										.calculateFileMD5(target);
								if (!Arrays.equals(chkSrc, chkTrg))
									til.markModified(m.getPackageNumber(), true);
							}
						}
					});
		}
	}

	/**
	 * @param tools
	 *            Tools to (un)install
	 * @param uninstall
	 *            Uninstall tools or install?
	 */
	public static void installTools(TreeSet<Package> tools, boolean uninstall) {
		ToolInstallationList til = ToolInstallationList.getInstance();
		for (Package m : tools) {
			if (!uninstall) { // Install:
				final HashSet<String> files = new HashSet<String>();
				ToolFileIterator.iteratePlatformToolFiles(m,
						new ToolFileIteratorEntry() {
							@Override
							public void toolFile(File source, File target) {
								copyToolsFiles(source, target, files);
							}
						});
				til.addTool(m.getPackageNumber(), files);
			} else { // Uninstall:
				if (til.isInstalled(m.getPackageNumber())) {
					removeTool(til.getFiles(m.getPackageNumber()));
					til.removeTool(m.getPackageNumber());
				}
			}
		}
		til.saveList();
	}

	private static void copyToolsFiles(File src, File target,
			HashSet<String> files) {
		try {
			File targetFile = CaseInsensitiveFile.getCaseInsensitiveFile(
					target.getParentFile(), target.getName());

			// Case mismatch?
			if (!targetFile.getName().equals(src.getName()))
				targetFile.delete();

			files.add(target.getPath().replace(
					Paths.getEditionBasePath().getPath(), ""));

			FileUtils.copyFile(src, target);
			if (src.canExecute())
				target.setExecutable(true);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void removeTool(HashSet<String> files) {
		for (String p : files) {
			File targetFile = new File(Paths.getEditionBasePath().getPath() + p);
			if (targetFile.getPath().contains(
					Paths.getEditionBasePath().getPath())) {
				File targetFolder = targetFile.getParentFile();

				if (targetFile.exists())
					targetFile.delete();
				if (targetFolder.list().length == 0)
					targetFolder.delete();
			}
		}
	}
}
