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

import java.io.File;

import com.interpress_project.modernshare.client.controller.command.exceptions.CommandException;
import com.interpress_project.modernshare.client.controller.delegate.LocalSVNManager;
import com.interpress_project.modernshare.client.controller.delegate.exceptions.ConnectionFailException;
import com.interpress_project.modernshare.client.controller.delegate.exceptions.InternalFailException;
import com.interpress_project.modernshare.client.controller.model.LocalRoot;
import com.interpress_project.modernshare.client.events.LogEvent;
import com.interpress_project.modernshare.client.events.LogEventType;
import com.interpress_project.modernshare.ipcommon.SystemBase;

public class SyncRemoteWithLocalCommand extends ISVNCommand {
	private final SystemBase sb = SystemBase.getInstance();
	private final LocalSVNManager svnmgr = LocalSVNManager.getInstance();
	private final SVNCommandManager cmdmgr = SVNCommandManager.getInstance();
	private final SVNCommandFactory factory = SVNCommandFactory.getInstance();
	private LocalRoot localRoot = null;
	private File rootpath;

	/**
	 * SyncRemoteWithLocalCommand
	 * @param localRoot
	 */
	public SyncRemoteWithLocalCommand(LocalRoot localRoot) {
		super();

		this.rootpath = new File(localRoot.getAbsolutePath());
		this.localRoot = localRoot;
	}

	/**
	 * execute
	 */
	public void execute() throws CommandException {
		logEventSource.fireEvent(new LogEvent(this, rootpath + "に格納されたデータでデータセンタを更新します...", LogEventType.INFO));

		localRoot.stopFsWatcher(); // 更新中はファイルシステム監視を停止する
		try {
			/**
			 * Main process
			 */
			_execute();

			localRoot.setDirty(false);

			/**
			 * Refresh both local and remote view.
			 */
			cmdmgr.addCommand(factory.createRemoteRefreshCommand());
			cmdmgr.addCommand(factory.createLocalRefreshCommand());
		}
		finally {
			localRoot.startFsWatcher();
			sb.getLogger().debug(sb.gc()); // Gabage collection.			
		}
		logEventSource.fireEvent(new LogEvent(this, rootpath + "への更新処理は成功しました。", LogEventType.INFO));
	}

	/**
	 * _execute
	 * @throws CommandException
	 */
	public void _execute() throws CommandException {
		sb.getLogger().debug("Enter SyncRemoteWithLocalCommand()._execute()");

		// Make a connection.
		try {
			svnmgr.connect();
		}
		catch (ConnectionFailException ex) {
			throw new CommandException(ex);
		}

		// SVN Cleanup
		try {
			svnmgr.cleanupFiles(rootpath);
		}
		catch (InternalFailException ex) {
			logEventSource.fireEvent(new LogEvent(this, "SVNクリーンアップ処理が失敗しました。処理を継続します。: " + ex.getMessage(),
			  LogEventType.INFO));
			// fall through...
		}

		try {
			/**
			 * ローカルでリモートを更新し、最終的なFile情報リストを返す。
			 */
			File[] files = svnmgr.prepareSyncRemoteFiles(rootpath);
			/**
			 * commitのためにrootpathを指定。(commitの引数には削除アイテムを指定できないようなのでrootpathを渡す。)
			 * 2番目のfilesはcommit中にファイルが消去された場合のチェックのため。
			 */
			svnmgr.commitDirectory(rootpath, files);
		}
		catch (InternalFailException ex) {
			throw new CommandException(ex);
		}
		sb.getLogger().debug("Leave SyncRemoteWithLocalCommand()._execute");
	}
}
