package ca.carleton.gcrc.couch.config.listener;

import java.io.File;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.URL;
import java.util.List;
import java.util.Properties;
import java.util.Vector;

import org.json.JSONObject;
import org.json.JSONTokener;

import ca.carleton.gcrc.couch.app.JSONFileLoader;
import ca.carleton.gcrc.couch.client.CouchClient;
import ca.carleton.gcrc.couch.client.CouchDb;
import ca.carleton.gcrc.couch.client.CouchFactory;

public class TestUtils {
	final static String DB_PREFIX = "delete";

	static public File getTestFile(String resourceName) {
		URL url = TestUtils.class.getClassLoader().getResource(resourceName);
		return new File(url.getFile());
	}
	
	static public File getTestResourceDir() {
		File testPropFile = getTestFile("test.properties.example");
		return testPropFile.getParentFile();
	}
	
	
	static private CouchClient g_client = null;
	static private boolean g_propsLoaded = false;
	
	static public CouchClient getClient() throws Exception {
		if( false == g_propsLoaded ) {
			InputStream propStream = 
				TestUtils.class.getClassLoader().getResourceAsStream("test.properties");
			if( null != propStream ) {
				Properties props = new Properties();
				props.load(propStream);
				
				CouchFactory couchFactory = new CouchFactory();
				g_client = couchFactory.getClient(props);
			}

			g_propsLoaded = true;
		}
		
		return g_client;
	}

	static int g_nextId = 0;
	static boolean g_oldDbsDeleted = false;
	static boolean g_testDbCreated = false;
	static CouchDb g_testDb = null;

	static public String getCouchDbName(CouchClient client) throws Exception {
		// Once, the first time called, delete old database so that names do not
		// clash from previous runs
		if( false == g_oldDbsDeleted ) {
			// Delete previous test databases
			List<String> dbsToDelete = new Vector<String>();
			List<String> dbs = client.listDatabases();
			for(String dbName : dbs) {
				if(dbName.startsWith(DB_PREFIX)) {
					dbsToDelete.add(dbName);
				}
			}
			for(String dbName : dbsToDelete) {
				CouchDb db = client.getDatabase(dbName);
				client.deleteDatabase(db);
			}
			
			g_oldDbsDeleted = true;
		}
		
		// Look for a new name
		int limit = 100;
		while( limit > 0 ) {
			String name = DB_PREFIX+g_nextId;
			++g_nextId;
			
			if( false == client.databaseExists(name) ) {
				return name;
			}
			
			--limit;
		}
		
		throw new Exception("Unable to find appropriate database name");
	}
	
	static public CouchDb getTestCouchDb() throws Exception {
		if( false == g_testDbCreated ) {
			CouchClient client = getClient();
			if( null != client ) {
				String name = getCouchDbName(client);
				CouchDb db = client.createDatabase(name);
				
				// Upload config design document...
				File configDdFile = new File(getTestResourceDir(), "configDesignDocument");

				// Load JSON string from directory structure
				JSONFileLoader builder = new JSONFileLoader(configDdFile);
				StringWriter sw = new StringWriter();
				builder.write(sw);
				
				// Get JSON from it
				JSONObject jsonObj = null;
				{
					JSONTokener jsonTokener = new JSONTokener(sw.toString());
					Object obj = jsonTokener.nextValue();
					if( obj instanceof JSONObject ) {
						jsonObj = (JSONObject)obj;

						// Assign id
						jsonObj.put("_id", "_design/config");
					} else {
						throw new Exception("Unexpected returned object type: "+obj.getClass().getSimpleName());
					}
				}
				
				// Create
				db.createDocument(jsonObj);
				
				g_testDb = db;
			}
			
			g_testDbCreated = true;
		}
		return g_testDb;
	}
}

@@ -95,37 +95,8 @@
 am;%0A
-import java.io.StringWriter;%0A
 impo
@@ -222,37 +222,52 @@
 ct;%0A
+%0A
 import 
-org.json.JSONTokener;%0A
+ca.carleton.gcrc.couch.app.Document;
 %0Aimp
@@ -297,30 +297,33 @@
 uch.app.
-JSONFileLoader
+impl.DocumentFile
 ;%0Aimport
@@ -462,16 +462,114 @@
 Factory;
+%0Aimport ca.carleton.gcrc.couch.fsentry.FSEntry;%0Aimport ca.carleton.gcrc.couch.fsentry.FSEntryFile;
 %0A%0Apublic
@@ -2929,428 +2929,226 @@
 %09%09%09%09
-// Load JSON string from directory structure%0A%09%09%09%09JSONFileLoader builder = new JSONFileLoader(configDdFile);%0A%09%09%09%09StringWriter sw = new StringWriter();%0A%09%09%09%09builder.write(sw);%0A%09%09%09%09%0A%09%09%09%09// Get JSON from it%0A%09%09%09%09JSONObject jsonObj = null;%0A%09%09%09%09%7B%0A%09%09%09%09%09JSONTokener jsonTokener = new JSONTokener(sw.toString());%0A%09%09%09%09%09Object obj = jsonTokener.nextValue();%0A%09%09%09%09%09if( obj instanceof JSONObject ) %7B%0A%09%09%09%09%09%09jsonObj = (JSONObject)obj;%0A%0A%09%09
+FSEntry designDocLocation = new FSEntryFile(configDdFile);%0A%09%09%09%09Document designDoc = DocumentFile.createDocument(designDocLocation);%0A%09%09%09%09%0A%09%09%09%09// Get JSON from it%0A%09%09%09%09JSONObject jsonObj = designDoc.getJSONObject();%0A%09%09%09%09%0A
 %09%09%09%09
@@ -3160,18 +3160,16 @@
 sign id%0A
-%09%09
 %09%09%09%09json
@@ -3206,130 +3206,8 @@
 %22);%0A
-%09%09%09%09%09%7D else %7B%0A%09%09%09%09%09%09throw new Exception(%22Unexpected returned object type: %22+obj.getClass().getSimpleName());%0A%09%09%09%09%09%7D%0A%09%09%09%09%7D%0A
 %09%09%09%09

Fix compilation issue.