//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 IBM Corporation and others.
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// Contributors:
// IBM Corporation - initial implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.importing.services;

import java.io.File;
import java.net.URI;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.epf.common.utils.FileUtil;
import org.eclipse.epf.library.util.ResourceHelper;
import org.eclipse.epf.persistence.MultiFileSaveUtil;
import org.eclipse.epf.uma.util.ContentDescriptionFactory;
import org.eclipse.epf.uma.util.IFileManager;


/**
 * utility class to copy files from one dir to another, and delete the un-needed files from source dir.
 *
 * @author Jinhua Xi
 * @since 1.0
 */
public class DirCopy {

	//private IStatus fileCheckedOutStatus = null;
	
	File srcDir;
	File targetDir;
	
	// new files to be added to the target
	List newFiles = new ArrayList();
	
	// files exists in both src and target dir
	List oldFiles = new ArrayList();
	
	// files only in target dir, these files are treated as deleted in the src folder.
	List deletedFiles = new ArrayList();
	
	public DirCopy(File srcDir, File targetDir) {
		this.srcDir = srcDir;
		this.targetDir = targetDir;
		
		prepare();
	}
	
	private static String CP_FODLER = MultiFileSaveUtil.CAPABILITY_PATTERN_PATH + "/"; //$NON-NLS-1$
	private static String DP_FODLER = MultiFileSaveUtil.DELIVERY_PROCESS_PATH + "/"; //$NON-NLS-1$
	
	/**
	 * check out the existing files, delete the files from cm, and add new files, copy the files over
	 *
	 */
	public IStatus execute() {
			
		// check out files
		List files = new ArrayList();
		for ( Iterator it = oldFiles.iterator(); it.hasNext(); ) {
			String path = (String)it.next();						
			if (needCopy(new File(srcDir, path), new File(targetDir, path))) {	//154321
				files.add(new File(targetDir, path).getAbsolutePath());
			}
		}
		
		IStatus fileCheckedOutStatus = FileModifyChecker.checkModify(files);
		
		if ( !fileCheckedOutStatus.isOK() ) {
			return fileCheckedOutStatus;
		}
			
		// delete files
		IFileManager fileMgr = ContentDescriptionFactory.getFileManager();
		for ( Iterator it = deletedFiles.iterator(); it.hasNext(); ) {
			String path = (String)it.next();
			File f = new File(targetDir, path);
			fileMgr.delete(f.getAbsolutePath());
			
			// delete the empty CP and DP folder
			path = path.replace(File.separatorChar, '/'); //$NON-NLS-1$
			if ( path.startsWith(CP_FODLER) || path.startsWith(DP_FODLER) ) {
				File folder = f.getParentFile();
				String[] items = folder.list();
				if ( items == null || items.length == 0 ) {
					fileMgr.delete(folder.getAbsolutePath());				
				}
			}
		}	
		
		// copy old files
		for ( Iterator it = oldFiles.iterator(); it.hasNext(); ) {
			String path = (String)it.next();
			ResourceHelper.copyFile(new File(srcDir, path), new File(targetDir, path));
		}
		
		// copy new files
		for ( Iterator it = newFiles.iterator(); it.hasNext(); ) {
			String path = (String)it.next();
			ResourceHelper.copyFile(new File(srcDir, path), new File(targetDir, path));
		}
		
		return fileCheckedOutStatus;
	}
	
	
	private void prepare() {
		List allSrcFiles = getAllFiles(srcDir);
		List allTargetFiles = getAllFiles(targetDir);

		while ( allTargetFiles.size() > 0 ) {
			String path = (String)allTargetFiles.remove(0);
			if ( allSrcFiles.contains(path) ) {
				oldFiles.add(path);
				allSrcFiles.remove(path);
			} else {
				deletedFiles.add(path);
			}
		}
		
		// the remaining files in the target list is the new files
		newFiles.addAll(allSrcFiles);
	}
	
	/**
	 * get all the files with relative path to the root
	 * @param dir the root dir
	 * @return List all files in the dir, with relative path to the root
	 */
	private List getAllFiles(File dir) {
		List files = new ArrayList();
		FileUtil.getAllFiles(dir, files, true);

		// convert to list of path, not File
		URI baseUrl = dir.toURI();
		
		int i = 0;
		while ( i < files.size() ) {
			File f = (File)files.get(i);
			if ( canIgnore(f.getAbsolutePath()) ) {
				files.remove(i);
			} else {
				URI rel = baseUrl.relativize(f.toURI());
				files.set(i, rel.getPath());	
				i++;
			}
		}

		return files;
	}
	
	private static final String CVS_FOLDER = File.separator + "CVS" + File.separator;
	private boolean canIgnore(String path) {
		if ( path.indexOf(CVS_FOLDER) >=0 ) {
			return true;
		}
		
		return false;
	}
	
	public static boolean needCopy(File source, File dest) {
		boolean ret = true;
		if (dest.exists()) {
			ret = (dest.lastModified() != source.lastModified())
					|| (dest.length() != source.length());
		}
		return ret;
	}
}
