package com.interpress_project.modernshare.serveradm;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;

import com.interpress_project.modernshare.ipcommon.SystemBase;
import com.interpress_project.modernshare.model.PropertyManager;
import com.interpress_project.modernshare.serveradm.exceptions.NoSVNInstalledException;
import com.interpress_project.modernshare.serveradm.exceptions.RepositoryException;

/**
 * @stereotype Manager
 */
public class SVNRepositoryManager {
	private final SystemBase sb = SystemBase.getInstance();
	private PropertyManager propmgr;
	private String svnadmin = null;

	/**
	 * @stereotype uses
	 */
	/*#com.interpress_project.modernshare.serveradm.CommandExecutor Dependency_Link*/

	/**
	 * SVNRepositoryManager 
	 */
	public SVNRepositoryManager() {

		propmgr = PropertyManager.getInstance();

		try {
			svnadmin = propmgr.getSVNAdminCommand();
		}
		catch (NoSVNInstalledException ex) {
			sb.getLogger().fatal(ex.getMessage(), ex);
			System.exit(-1);
		}

		/**
		 * Check existance backup dir.
		 */
		String targetDir = propmgr.getSVNBackupdir();
		File dir = new File(targetDir);

		if (!dir.exists()) {
			if (!dir.mkdirs()) {
				sb.getLogger().fatal("Unable to create the backup directory, " + targetDir + ". Server is forcely terminated.");
				System.exit(-1);
			}
			sb.getLogger().warn("The backup directory " + targetDir + " created.");
		}
		if (!dir.isDirectory()) {
			if (!dir.delete()) {
				sb.getLogger().fatal("Tried to create backup directory, but found the plain file there.");
				sb.getLogger().fatal("Unable to delete file, " + targetDir + ". Server is forcely terminated.");
				System.exit(-1);
			}
			if (!dir.mkdirs()) {
				sb.getLogger().fatal("Unable to create the backup directory, " + targetDir + ". Server is forcely terminated.");
				System.exit(-1);
			}
			sb.getLogger().warn("The backup directory " + targetDir + " created.");
		}

		/**
		 * existance test of the repository.
		 */
		if (existRepository()) {
			try {
				cleanTransaction();
			}
			catch (RepositoryException ex) {
				sb.getLogger().fatal(ex.toString());
				System.exit(-1);
			}
			return;
		}
		else { // Repository not exist.
			try {
				createRepository();
			}
			catch (RepositoryException ex) {
				sb.getLogger().fatal(ex.toString());
				System.exit(-1);
			}
		}
	}

	/**
	 * existRepository
	 * @return
	 */
	private boolean existRepository() {
		String rootdir = propmgr.getSVNRootdir();
		File file = new File(rootdir);
		if (!file.exists()) {
			return false;
		}
		if (!file.isDirectory()) {
			return false;
		}
		return true;
	}

	/**
	 * createRepository
	 * @throws Throwable 
	 */
	public void createRepository() throws RepositoryException {
		ArrayList<String> list = new ArrayList<String>();
		String rootdir = propmgr.getSVNRootdir();

		sb.getLogger().debug("Enter createRepository()");
		sb.getLogger().info("Creating new repository in " + rootdir + ". It may take time ...");

		/**
		 * Create empty repository.
		 */
		try {
			list.add(svnadmin);
			list.add("create");
			if (propmgr.hasBdbused()) {
				list.add("--fs-type");
				list.add("bdb");
			}
			list.add(rootdir);
			new CommandExecutor(true).execute(list);
		}
		catch (Throwable ex) {
			throw new RepositoryException(ex);
		}
		sb.getLogger().info("Creating new repository done.");
	}

	/**
	 * cleanTransaction
	 * @throws RepositoryException
	 */
	public void cleanTransaction() throws RepositoryException {
		ArrayList<String> list = new ArrayList<String>();
		int retval = -1;

		sb.getLogger().warn("Cleaning up the repository. It may take time ...");
		String rootdir = propmgr.getSVNRootdir();

		try {
			list.add(svnadmin);
			list.add("recover");
			list.add(rootdir);
			retval = new CommandExecutor(true).execute(list);
		}
		catch (Throwable ex) {
			throw new RepositoryException(ex);
		}

		if (retval != 0) {
			throw new RepositoryException("Fail to clean up the repository.(" + list.toString() + ")");
		}
		sb.getLogger().warn("Cleaning up done.");
	}

	/**
	 * backup
	 * @throws Throwable 
	 */
	public String backup() throws Throwable {
		ArrayList<String> list = new ArrayList<String>();
		String srcDir = propmgr.getSVNRootdir();
		String d = sb.getDateUtil().getDateTimeAsDecimal(new Date());
		String targetDir = propmgr.getSVNBackupdir();
		targetDir = targetDir + "/" + d;

		sb.getLogger().info("Backing up the repository to " + targetDir + ". It may take time ...");

		try {
			list.add(svnadmin);
			list.add("hotcopy");
			list.add(srcDir);
			list.add(targetDir);
			new CommandExecutor(true).execute(list);
		}
		catch (Throwable ex) {
			throw new RepositoryException("Fail to back up the repository.(" + list.toString() + ")");
		}
		sb.getLogger().info("Backing up done.");
		return d;
	}
}
