package org.easycassandra.persistence.cassandra;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.datastax.driver.core.DataType;
import com.datastax.driver.core.DataType.Name;
import com.datastax.driver.core.Row;

/**
 * this enum contains the relationship between CQL's type rows and type Java.
 * @author otaviojava
 * @version 1.0
 */
enum RelationShipJavaCassandra {
    INSTANCE;

    /**
     * key is cql and value is Java.
     */
    private Map<String, String> mapCQL;
    /**
     * key is Java and value is CQL.
     */
    private Map<String, List<String>> mapJava;

    {
        mapCQL = new HashMap<String, String>();

        mapJava = new HashMap<String, List<String>>();

        for (DataType.Name name : DataType.Name.values()) {
            String cqlType = name.name().toLowerCase();
            String javaType = name.asJavaClass().getName();
            List<String> cqlvalues = mapJava.get(javaType);
            if (cqlvalues == null) {
                cqlvalues = new LinkedList<String>();
                mapJava.put(javaType, cqlvalues);
            }
            cqlvalues.add(cqlType);
            mapCQL.put(cqlType, javaType);
        }

    }

    /**
     * methods returns the equivalent type in Java from CQL type.
     * @param cqlType
     *            - cqlTypeKey
     * @return the java type
     */
    public String getJavaValue(String cqlTypeKey) {
        return mapCQL.get(cqlTypeKey);
    }

    /**
     * methods returns the equivalent type in CQL from Java type.
     * @param cqlType
     *            - javaTypeKey
     * @return the java type
     */
    public List<String> getCQLType(String javaTypeKey) {
        return mapJava.get(javaTypeKey);
    }

    public String getPreferenceCQLType(String javaTypeKey) {

        if (String.class.getName().equals(javaTypeKey)) {
            return DataType.Name.TEXT.name().toLowerCase();
        } else if (Long.class.getName().endsWith(javaTypeKey)) {
            return DataType.Name.BIGINT.name().toLowerCase();
        }

        return getCQLType(javaTypeKey).get(0);
    }

    /**
     * return the object using relationship Java.
     * @param row the row
     * @param cqlType the cqltype
     * @param name the name
     * @param classes the Classes
     * @param <T> kind of object
     * @return the object
     */
    public Object getObject(Row row, Name cqlType, String name,
            Class<?>... classes) {
        switch (cqlType) {
        case ASCII:
        case TEXT:
        case VARCHAR:
            return row.getString(name);
        case BIGINT:
        case COUNTER:
            return row.getLong(name);
        case BOOLEAN:
            return row.getBool(name);
        case BLOB:
        case CUSTOM:
            return row.getBytes(name);
        case DECIMAL:
            return row.getDecimal(name);
        case DOUBLE:
            return row.getDouble(name);
        case FLOAT:
            return row.getFloat(name);
        case INT:
            return row.getInt(name);
        case VARINT:
            return row.getVarint(name);
        case TIMESTAMP:
            return row.getDate(name);
        case UUID:
        case TIMEUUID:
            return row.getUUID(name);
        case LIST:
            return row.getList(name, classes[0]);
        case MAP:
            return row.getMap(name, classes[0], classes[1]);
        case SET:
            return row.getSet(name, classes[0]);
        case INET:
            return row.getInet(name);

        default:
            break;
        }

        return null;
    }
}

@@ -142,16 +142,42 @@
 til.Map;
+%0Aimport java.util.TreeMap;
 %0A%0Aimport
@@ -562,16 +562,62 @@
 mapCQL;%0A
+    private Map%3CString, String%3E primitiveMap;%0A
     /**%0A
@@ -740,30 +740,16 @@
 new 
-HashMap%3CString, String
+TreeMap%3C
 %3E();
@@ -776,37 +776,84 @@
 new 
-HashMap%3CString, List%3CString%3E%3E
+TreeMap%3C%3E();%0A%0A        primitiveMap = new TreeMap%3C%3E();%0A%0A        initPrimitive
 ();%0A
@@ -1169,22 +1169,16 @@
 kedList%3C
-String
 %3E();%0A   
@@ -1327,32 +1327,511 @@
       %7D%0A%0A    %7D%0A%0A
+    private void initPrimitive() %7B%0A        primitiveMap.put(%22byte%22, %22java.lang.Byte%22);%0A        primitiveMap.put(%22short%22, %22java.lang.Short%22);%0A        primitiveMap.put(%22char%22, %22java.lang.Character%22);%0A        primitiveMap.put(%22int%22, %22java.lang.Integer%22);%0A        primitiveMap.put(%22long%22, %22java.lang.Long%22);%0A        primitiveMap.put(%22float%22, %22java.lang.Float%22);%0A        primitiveMap.put(%22Double%22, %22java.lang.Double%22);%0A        primitiveMap.put(%22boolean%22, %22java.lang.Boolean%22);%0A    %7D%0A%0A
     /**%0A     * m
@@ -2290,32 +2290,176 @@
  javaTypeKey) %7B%0A
+        String primitive = primitiveMap.get(javaTypeKey);%0A        if (primitive != null) %7B%0A            return mapJava.get(primitive);%0A        %7D%0A
         return m
@@ -2799,32 +2799,193 @@
 se();%0A        %7D%0A
+        String primitiveType = primitiveMap.get(javaTypeKey);%0A        if (primitiveType != null) %7B%0A            return getCQLType(primitiveType).get(0);%0A        %7D
 %0A        return 

add primitive type