package org.eclipse.team.tests.ccvs.core;
/*
 * (c) Copyright IBM Corp. 2000, 2002.
 * All Rights Reserved.
 */
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;

import junit.awtui.TestRunner;
import junit.framework.TestCase;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.team.internal.ccvs.core.CVSException;
import org.eclipse.team.internal.ccvs.core.ICVSRepositoryLocation;
import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;

/**
 * Base-class to the low level-testcases for the Session.
 * Supplies convinience-methods and default attributes for the testcases.
 * Especally data for a default-connection to the server is stored.
 */
public abstract class JUnitTestCase extends TestCase {
	protected static final int RANDOM_CONTENT_SIZE = 10000;
	protected static final boolean NEWLINE_TEST = false;
	protected static final String PLATFORM_NEWLINE = System.getProperty("line.separator");
	protected static final IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
	
	public static final String[] EMPTY_ARGS = new String[0];

	/**
	 * Init the options and arguments to standard-values
	 */
	public JUnitTestCase(String name) {
		super(name);
	}

	/**
	 * Delete a project/resource form the standard cvs-server
	 */
	protected void magicDeleteRemote(String remoteName) throws CVSException {
		magicDeleteRemote(CVSTestSetup.repository, remoteName);
	}

	/**
	 * Delete a project/resource form the specified cvs-server
	 */
	protected static void magicDeleteRemote(ICVSRepositoryLocation location, String remoteName)
		throws CVSException {
		CVSTestSetup.executeRemoteCommand(location, "rm -rf " + 
			new Path(location.getRootDirectory()).append(remoteName).toString());
	}

	/**
	 * Sends the project to the standard cvs-server so that it contains the resources
	 * described in createResources.  The files have random content.
	 *
	 * @param projectName the name of the project to import
	 * @param createResources e.g. new String[]{"a.txt","f1/b.txt","f1/c.txt","f2/d.txt"}
	 */
	protected void magicSetUpRepo(String projectName, String[] createResources)
		throws  IOException, CoreException, CVSException {
		magicSetUpRepo(CVSTestSetup.repository, projectName, createResources);
	}
	
	/**
	 * Sends the project to the specified cvs-server so that it contains the resources
	 * described in createResources.  The files have random content.
	 * 
	 * @param location the CVS repository location
	 * @param projectName the name of the project to import
	 * @param createResources e.g. new String[]{"a.txt","f1/b.txt","f1/c.txt","f2/d.txt"}
	 */
	protected static void magicSetUpRepo(ICVSRepositoryLocation location, String projectName,
		String[] createResources) throws IOException, CoreException, CVSException {
		IProject projectRoot = workspaceRoot.getProject(projectName + "-setup-tmp");
		mkdirs(projectRoot);
		createRandomFile(projectRoot, createResources);
		magicDeleteRemote(location, projectName);
		
		String[] lOptions = new String[]{"-m","msg"};
		String[] args = new String[]{projectName,"a","b"};
	
		EclipseCVSClient.execute(location, CVSWorkspaceRoot.getCVSFolderFor(projectRoot),
			"import", EMPTY_ARGS, lOptions, args);
		projectRoot.delete(false /*force*/, null);
	}
	
	/**
	 *  Compare Arrays and find the first different element
	 */
	protected static void assertEqualsArrays(Object[] obArr1, Object[] obArr2) {
		
		assertEquals("Called assertEqualsArrays with null on one side", obArr1 == null,obArr2 == null);
		if (obArr1 == null) {
			return;
		}

		for (int i=0; i<Math.min(obArr1.length,obArr2.length); i++) {
			assertEquals("At Element " + i + " of the array",obArr1[i],obArr2[i]);
		}
		
		// If the Arrays are different in length, look for the first
		// not existing element and compare it to the existing in the
		// other array
		if (obArr1.length > obArr2.length) {
			assertEquals("Arrays of different length",obArr1[obArr2.length],null);
			return;
		}
	
		if (obArr1.length < obArr2.length) {
			assertEquals("Arrays of different length",obArr2[obArr1.length],null);
			return;
		}
			
	}
	
	/**
	 * Write text lines to file from an array of strings.
	 */
	protected static void writeToFile(IFile file, String[] contents)
		throws IOException, CoreException {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		PrintStream os = new PrintStream(bos);
		try {
			for (int i = 0; i < contents.length; i++) {
				os.println(contents[i]);
			}
			ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
			if (file.exists()) {
				file.setContents(bis, false /*force*/, true /*keepHistory*/, null);
			} else {
				mkdirs(file.getParent());
				file.create(bis, false /*force*/, null);
			}
		} finally {
			os.close();
		}
	}
	
	/**
	 * Read text lines from file into an array of strings.
	 */
	protected static String[] readFromFile(IFile file)
		throws IOException, CoreException {
		if (! file.exists()) return null;
		BufferedReader reader = new BufferedReader(new InputStreamReader(file.getContents()));
		List fileContentStore = new ArrayList();
		try {
			String line;
			while ((line = reader.readLine()) != null) {
				fileContentStore.add(line);
			}			
		} finally {
			reader.close();
		}
		return (String[]) fileContentStore.toArray(new String[fileContentStore.size()]);
	}

	/**
	 * Append text files to file from an array of strings, create new file if it
	 * does not exist yet.
	 */
	protected static void appendToFile(IFile file, String[] contents)
		throws IOException, CoreException {
		String[] oldContents = readFromFile(file);
		String[] newContents;
		if (oldContents == null) {
			newContents = contents;
		} else {
			newContents = new String[oldContents.length + contents.length];
			System.arraycopy(oldContents, 0, newContents, 0, oldContents.length);
			System.arraycopy(contents, 0, newContents, oldContents.length, contents.length);
		}
		writeToFile(file, newContents);
	}
	
	/**
	 * Pre-Append text files to file from an array of strings, create new file if it
	 * does not exist yet.
	 */
	protected static void prefixToFile(IFile file, String[] contents)
		throws IOException, CoreException {
		String[] oldContents = readFromFile(file);
		String[] newContents;
		if (oldContents == null) {
			newContents = contents;
		} else {
			newContents = new String[oldContents.length + contents.length];
			System.arraycopy(contents, 0, newContents, 0, contents.length);
			System.arraycopy(oldContents, 0, newContents, contents.length, oldContents.length);
		}
		writeToFile(file, newContents);
	}
	
	/**
	 * genertates Random content meand to be written in a File
	 */
	protected static String createRandomContent() {
		
		StringBuffer content = new StringBuffer();
		int contentSize;
		
		content.append("Random file generated for test" + PLATFORM_NEWLINE);
		
		contentSize = (int) Math.round(RANDOM_CONTENT_SIZE * 2 * Math.random());
		for (int i=0; i<contentSize; i++) {
			
			if (Math.random()>0.99) {
				content.append(PLATFORM_NEWLINE);
			}

			if (Math.random()>0.99) {
				content.append("\n");
			}
			
			if (NEWLINE_TEST) {
				if (Math.random()>0.99) {
					content.append("\n\r");
				}
				if (Math.random()>0.99) {
					content.append('\r');
				}
				if (Math.random()>0.99) {
					content.append("\r\n");
				}
				if (Math.random()>0.99) {
					content.append("\n");
				}
				if (Math.random()>0.99) {
					content.append("\n\n");
				}
				if (Math.random()>0.99) {
					content.append("\r\r");
				}
			}
			
			content.append((char)('\u0021' + Math.round(60 * Math.random())));
		}
		
		return content.toString();
	}
	
	/**
	 * Creates a folder (and its parents if needed).
	 */
	protected static void mkdirs(IContainer container) throws CoreException {
		if (container.getType() == IResource.PROJECT) {
			IProject project = (IProject) container;
			if (! project.exists()) {
				project.create(null);
			}
			project.open(null);
		} else if (container.getType() == IResource.FOLDER) {
			IFolder folder = (IFolder) container;
			if (! folder.exists()) {
				mkdirs(folder.getParent());
				folder.create(false /*force*/, true /*local*/, null);
			}
		}
	}

	/**
	 * Creates the file with random content, and all the folders on the
	 * way to there.
	 */
	private static void createRandomFile(IFile file)
		throws IOException, CoreException {
		mkdirs(file.getParent());
		writeToFile(file, new String[] { createRandomContent() });
	}
		
	/**
	 * Build the given fileStructure, all files are going to have
	 * sample content, all folders on the way are created.
	 */
	protected static void createRandomFile(IContainer parent, String[] fileNameArray) 
		throws IOException, CoreException {
		for (int i = 0; i < fileNameArray.length; i++) {
			IFile file = parent.getFile(new Path(fileNameArray[i]));
			createRandomFile(file);
		}
	}

	/**
	 * wait milliseconds to continou the execution
	 */
	public static void waitMsec(int msec) {	
		try {
			Thread.currentThread().sleep(msec);
		} catch(InterruptedException e) {
			fail("wait-problem");
		}
	}
	
	/**
	 * Call this method from the main-method of your test-case.
	 * It initialises some required parameter and runs the testcase.
	 */
	protected static void run(Class test) {
		// XXX is this property used anywhere?
		System.setProperty("eclipse.cvs.standalone", "true");
		TestRunner.run(test);
	}
}

