package org.bench4q.agent.plugin.basic.MongoDB;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.log4j.Logger;
import org.bench4q.agent.plugin.Constructor;
import org.bench4q.agent.plugin.Parameter;
import org.bench4q.agent.plugin.Plugin;
import org.bench4q.agent.plugin.behavior.Behavior;
import org.bench4q.agent.plugin.behavior.BehaviorType;
import org.bench4q.agent.utils.Type.SupportTypes;
import org.bench4q.agent.utils.types.Table;
import org.bench4q.agent.utils.types.Table.Row;

import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoOptions;
import com.mongodb.ServerAddress;

@SuppressWarnings("deprecation")
@Plugin("MongoDBPlugin")
public class MongoDBPlugin {
	private final String hostName;
	private final String dbName;
	private final String tableUnderTest = "users";

	@Constructor
	public MongoDBPlugin(
			@Parameter(value = "hostName", type = SupportTypes.Field) String hostName,
			@Parameter(value = "port", type = SupportTypes.Field) int port,
			@Parameter(value = "dbName", type = SupportTypes.Field) String dbName) {
		this.hostName = hostName;
		this.dbName = dbName;
	}

	@Behavior(value = "Insert", type = BehaviorType.USER_BEHAVIOR)
	public MongoDBReturn insert(
			@Parameter(value = "key", type = SupportTypes.Field) String key,
			@Parameter(value = "value", type = SupportTypes.Field) String value) {
		Mongo mongo = null;
		try {
			List<ServerAddress> hostsList = new ArrayList<ServerAddress>();
			String[] hosts = hostName.split(",");
			for(String host : hosts)
			{
			    hostsList.add(new ServerAddress(host));	
			}
			 
			mongo = new Mongo(hostsList ,  
					new MongoOptions(new MongoClientOptions.Builder()
					.maxWaitTime(1000 * 40).build()));
			/*mongo = new Mongo(new ServerAddress(hostName, port),
					new MongoOptions(new MongoClientOptions.Builder()
							.maxWaitTime(1000 * 40).build()));
	         */
			DB db = mongo.getDB(dbName);
			DBCollection table = db.getCollection(this.tableUnderTest);
			DBObject valueToInsert = new BasicDBObject();
			valueToInsert.put("key", key);
			valueToInsert.put("value", value);
			table.save(valueToInsert);
			return new MongoDBReturn(true);
		} catch (Exception e) {
			e.printStackTrace();
			return new MongoDBReturn(false);
		} finally {
			if (mongo != null) {
				mongo.close();
			}
		}

	}

	@Behavior(value = "Query", type = BehaviorType.USER_BEHAVIOR)
	public MongoDBReturn query(
			@Parameter(value = "properties", type = SupportTypes.Table) String properties) {
		Mongo mongo = null;
		try {
			List<ServerAddress> hostsList = new ArrayList<ServerAddress>();
			String[] hosts = hostName.split(",");
			for(String host : hosts)
			{
			    hostsList.add(new ServerAddress(host));	
			}
			 
			mongo = new Mongo(hostsList ,  
					new MongoOptions(new MongoClientOptions.Builder()
					.maxWaitTime(1000 * 40).build()));			 
			DB db = mongo.getDB(dbName);
			DBCollection table = db.getCollection(this.tableUnderTest);
			Table propertiesTable = Table.buildTable(properties,
					Arrays.asList("propertyName", "propertyValue"));
			BasicDBObject query = new BasicDBObject();
			for (Row row : propertiesTable.getRows()) {
				String propertyName = row.getCell("propertyName");
				String propertyValue = row.getCell("propertyValue");
				query.append(propertyName, propertyValue);
			}
			System.out.println(query);
			DBCursor queryResult = table.find(query);
			for (DBObject item : queryResult.toArray()) {
				System.out.println(item);
			}
			return new MongoDBReturn(true);
		} catch (Exception e) {
			Logger.getLogger(this.getClass()).info(e, e);
			return new MongoDBReturn(false);
		} finally {
			if (mongo != null) {
				mongo.close();
			}
		}

	}
}