package com.woextras.eo.utilities;

import java.util.Enumeration;
import java.util.Iterator;

import com.webobjects.eoaccess.EOEntity;
import com.webobjects.eoaccess.EOUtilities;
import com.webobjects.eocontrol.EOEditingContext;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSDictionary;
import com.webobjects.foundation.NSKeyValueCoding;
import com.webobjects.foundation.NSLog;
import com.webobjects.foundation.NSMutableArray;
import com.webobjects.foundation.NSMutableDictionary;
import com.woextras.Timer;
import com.xerox.amazonws.sdb.Domain;
import com.xerox.amazonws.sdb.Item;
import com.xerox.amazonws.sdb.ItemAttribute;
import com.xerox.amazonws.sdb.ListDomainsResult;
import com.xerox.amazonws.sdb.SDBException;
import com.xerox.amazonws.sdb.SimpleDB;

public class CopyEOAttributesToSimpleDBThread extends Thread
{
	private static NSDictionary domains;
	EOGenericRecord eo = null;
	boolean shouldOverwrite = true;
	
	static
	{
		Timer timer = Timer.startNewTimer();
		NSLog.debug.appendln("Loading domains from SimpleDB.");
		SimpleDB simpleDB = new SimpleDB(Property.AWS_ACCESS_ID(), Property.AWS_SECRET_KEY(), true);

		
		NSMutableDictionary domainsList = new NSMutableDictionary();
		
		try
		{
			ListDomainsResult listDomainResults = simpleDB.listDomains();
			NSLog.debug.appendln("List of domains = " + listDomainResults.getDomainList());
			Iterator iterator = listDomainResults.getDomainList().iterator();
			while (iterator.hasNext())
			{
				Domain domain = (Domain) iterator.next();
				NSLog.debug.appendln("Domain: " + domain.getName());
				domainsList.setObjectForKey(domain, domain.getName());
			}
			domains = new NSMutableDictionary(domainsList);
		} catch (SDBException e1)
		{
			e1.printStackTrace();
			// INFO: What do you do if SimpleDB is down?
		}
		
		NSLog.debug.appendln("Domains = " + domains);
		NSLog.debug.appendln("Finished loading domains from SimpleDB.");
		timer.stopTime();
		NSLog.debug.appendln("List all domains elapsed time: " + timer.elapsedTime());

	}
	
	public CopyEOAttributesToSimpleDBThread(EOGenericRecord newEO)
	{
		eo = newEO;

		// INFO: Replace OID with the column name of your table's PK.
		String oid = (((NSDictionary)
					 EOUtilities.primaryKeyForObject((new EOEditingContext(), this)).
					valueForKey("oid")).toString();
		}
		
		this.setName("CopyEOAttributesToSimpleDBThread - " + newEO.entityName() + " (" + oid + ")");
	}

	public CopyEOAttributesToSimpleDBThread(EOGenericRecord newEO, boolean shouldOverwrite)
	{
		this(newEO);
		this.shouldOverwrite = shouldOverwrite;
	}

	
	public void run()
	{

		NSLog.debug.appendln("Entering thread.");
		
		String oidString = (((NSDictionary)
							EOUtilities.primaryKeyForObject(new EOEditingContext(), this)).
							valueForKey("oid")).toString();

		EOEntity eoEntity = EOUtilities.entityNamed(new EOEditingContext(), eo.entityName());
		String externalName = eoEntity.externalName();

		// INFO: Replace OID with the column name of your table's PK.
		String sqlString = "SELECT * FROM " + externalName + " WHERE OID =" + oidString;
		
		NSArray results = EOUtilities.rawRowsForSQL(new EOEditingContext(), "MyEOModel", sqlString, null);
		
		if (results.count() > 0)
		{
			NSLog.debug.appendln("Results = " + results.objectAtIndex(0));
			
			String domainName = externalName;
			// INFO: SimpleDB domains (aka RDMS Tables) must be at least three characters long.
			// if the current EO entity name is less than three characters then append _TABLE.
			if (domainName.length() < 3)
			{
				domainName = domainName + "_TABLE";
			}
			
			Domain domain = (Domain) domains.objectForKey(domainName);
			Item item = null;
			
			try
			{
				// INFO: Unintuitively, the getItem() method will create a new Item in SimpleDB if
				// one doesn't already exist with this ItemID.
				item = domain.getItem(oidString);
			} catch (SDBException e1)
			{
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			
			if (item != null)
			{
				NSDictionary keyValues = (NSDictionary) results.objectAtIndex(0);
				Enumeration enumeration = keyValues.keyEnumerator();
				NSMutableArray itemAttributes = new NSMutableArray();
				while (enumeration.hasMoreElements())
				{
					String key = (String) enumeration.nextElement();
					Object objectValue = keyValues.objectForKey(key);
					if ( !(objectValue instanceof NSKeyValueCoding.Null))
					{
						String value = objectValue.toString();
						ItemAttribute itemAttribute = new ItemAttribute(key, value,	shouldOverwrite);
						itemAttributes.addObject(itemAttribute);
					}
				}
				NSLog.debug.appendln("About to save item to SimpleDB");
				Timer timer = Timer.startNewTimer();
				try {
					item.putAttributes(itemAttributes);
					timer.stop();
					NSLog.debug.appendln("Saved item to SimpleDB: " + itemAttributes);
					NSLog.debug.appendln("Elapsed time: " + timer.elapsedTime());
				} catch (SDBException exception)
				{
					// TODO: If this fails then it usually means that SimpleDB is down
					// or "experiencing elevated error rates" which means the data wasn't saved.
					// It should be written as a plist to a temp file (*not* under /tmp) and, upon WO app
					// startup, that file should be read and written to SimpleDB.
					NSLog.debug.appendln("\n********** Exception saving to SimpleDB: " + exception);
					exception.printStackTrace();
				}
			}
		} else
		{
			NSLog.debug.appendln("\n********** Problem getting row for: " + eo + "\n");
		}

	
	}

}
