package com.interpress_project.modernshare.client.controller.delegate;

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

import org.apache.commons.io.FileUtils;

import com.interpress_project.modernshare.AppKeys;
import com.interpress_project.modernshare.client.controller.delegate.exceptions.DeleteFailException;
import com.interpress_project.modernshare.client.controller.delegate.exceptions.RenameFailException;
import com.interpress_project.modernshare.client.events.LogEvent;
import com.interpress_project.modernshare.client.events.LogEventSource;
import com.interpress_project.modernshare.client.events.LogEventType;
import com.interpress_project.modernshare.ipcommon.SystemBase;

/**
 * Represents a singleton.
 * @stereotype Singleton factory
 */

public class SVNFolderUtil {
	private ArrayList<File> list1 = null, list2 = null;
	private File rootFolder;
	private final LogEventSource logEventSource = LogEventSource.getInstance();
	private final SystemBase sb = SystemBase.getInstance();

	/**
	 * SVNFolderUtil
	 */
	private SVNFolderUtil() {
	}

	/**
	 * getSVNDirListInTarget
	 * @param folder
	 * @return
	 */
	public ArrayList<File> getSVNDirListInTarget(File folder) {
		this.rootFolder = folder;
		this.list1 = new ArrayList<File>(64);
		_getSVNDirList(rootFolder);
		list1.trimToSize();
		return list1;
	}

	/**
	 * _getSVNDirList
	 * @param dir
	 */
	private void _getSVNDirList(File dir) {
		if (dir.isDirectory()) {
			String[] children = dir.list();
			for (int i = 0; i < children.length; i++) {
				_getSVNDirList(new File(dir, children[i]));
			}
		}
		if (dir.getName().equalsIgnoreCase(".svn")) {
			list1.add(dir);
		}
	}

	/**
	 * getDirListInTarget
	 * 結果のリストには渡されたfolderは含まれない。
	 * @param folder
	 * @return
	 */
	public ArrayList<File> getDirListInTarget(File folder) {
		this.list2 = new ArrayList<File>(64);
		File[] files = folder.listFiles();
		for (int i = 0; i < files.length; i++) {
			_getDirList(files[i]);
		}
		Collections.sort(list2);
		list2.trimToSize();
		return list2;
	}

	/**
	 * _getDirList
	 * @param dir
	 */
	private void _getDirList(File dir) {
		if (dir.isDirectory()) {
			if (dir.getName().equalsIgnoreCase(".svn")) {
				return;
			}
			String[] children = dir.list();
			for (int i = 0; i < children.length; i++) {
				_getDirList(new File(dir, children[i]));
			}
			list2.add(dir);
		}
	}

	/**
	 * deleteFiles
	 * @param list
	 * @throws DeleteFailException
	 */
	public void deleteFiles(ArrayList<File> list) throws DeleteFailException {
		for (int i = 0; i < list.size(); i++) {
			File file = list.get(i);
			deleteFile(file);
		}
	}

	/**
	 * deleteFile
	 * ファイル、フォルダの削除
	 * @param dir
	 * @throws DeleteFailException
	 */
	public void deleteFile(File dir) throws DeleteFailException {
		if (!dir.exists()) {
			return;
		}
		try {
			if (dir.isDirectory()) {
				FileUtils.deleteDirectory(dir);
			}
			else {
				FileUtils.forceDelete(dir);
			}
		}
		catch (IOException ex) {
			throw new DeleteFailException("ローカルファイル" + dir.getAbsolutePath() + "の削除に失敗しました。");
		}
		logEventSource.fireEvent(new LogEvent(this, dir.getAbsolutePath() + "を削除しました。", LogEventType.INFO));
	}

	/**
	 * deleteSVNFolders
	 * SubVersion管理フォルダのみを削除
	 * @param file
	 * @throws DeleteFailException
	 */
	public void deleteSVNFolders(File file) throws DeleteFailException {
		ArrayList<File> list = getSVNDirListInTarget(file);
		deleteFiles(list);
	}

	/**
	 * renameFile
	 * @param src
	 * @param dest
	 * @throws RenameFailException
	 */
	public void renameFile(File src, File dest) throws RenameFailException {
		if (src.renameTo(dest) == false) {
			throw new RenameFailException(src.getAbsolutePath() + "から" + dest.getAbsolutePath() + "への名前変更に失敗しました。");
		}
		logEventSource.fireEvent(new LogEvent(this, src.getAbsolutePath() + "を" + dest.getAbsolutePath() + "に名前変更をしました。",
		  LogEventType.INFO));
	}

	/**
	 * renameBkupFile
	 * @param src
	 * @throws RenameFailException
	 */
	public void renameBkupFile(File src) throws RenameFailException {
		String bkuppath = src.getAbsolutePath();
		String date = sb.getDateUtil().getDateTimeAsFullString(new Date());
		date = date.replaceAll(" ", "");
		bkuppath = bkuppath + "." + date + "." + AppKeys.HOTSHOTBKUPFILE;
		File bkupfile = new File(bkuppath);
		if (src.renameTo(bkupfile) == false) {
			throw new RenameFailException(src.getAbsolutePath() + "から" + bkupfile.getAbsolutePath() + "への名前変更に失敗しました。");
		}
		logEventSource.fireEvent(new LogEvent(this, src.getAbsolutePath() + "を" + bkupfile.getAbsolutePath()
		    + "に名前変更をしました。", LogEventType.INFO));
	}

	/**
	 * Returns the singleton instance.
	 @return	the singleton instance
	 */
	static public SVNFolderUtil getInstance() {
		return new SVNFolderUtil();
	}
}
