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,
								boolean isDir) {
							byte[] chkSrc = FileChecksum
									.calculateFileMD5(source);
							if (!target.exists()) {
								til.markModified(m.getPackageNumber(), true);
							} else {
								if (!isDir) {
									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,
									boolean isDir) {
								copyToolsFiles(source, target, isDir, 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, boolean isDir,
			HashSet<String> files) {
		try {
			File targetFile = CaseInsensitiveFile.getCaseInsensitiveFile(
					target.getParentFile(), target.getName());

			if (isDir && src.getAbsolutePath().endsWith(".app")) {
				files.add(target.getPath().replace(
						Paths.getEditionBasePath().getPath(), ""));

				if (targetFile.exists()) {
					FileUtils.deleteDirectory(targetFile);
				}

				FileUtils.copyDirectory(src, target, true);
			} else {
				if (!src.getAbsolutePath().contains(".app/")) {
					files.add(target.getPath().replace(
							Paths.getEditionBasePath().getPath(), ""));

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

					FileUtils.copyFile(src, target);
				}

				if (src.canExecute() && targetFile.exists())
					targetFile.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()) {
					if (targetFile.isDirectory()) {
						try {
							FileUtils.deleteDirectory(targetFile);
						} catch (IOException e) {
							e.printStackTrace();
						}
					} else
						targetFile.delete();
				}
				if (targetFolder.list().length == 0)
					targetFolder.delete();
			}
		}
	}
}
