package com.github.cleverage.elasticsearch;

import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.xcontent.XContentBuilder;
import play.Logger;

import java.math.BigDecimal;
import java.util.*;

public abstract class IndexUtils {

    public static <T extends Indexable> List<T> getIndexables(Map map, String key, Class<T> t) {
        List<Map<String, Object>> mapList = (List<Map<String, Object>>) map.get(key);
        List<T> list = new ArrayList<T>();
        if (mapList != null) {
            for (Map<String, Object> map1 : mapList) {
                list.add(getIndexable(map1, t));
            }
        }
        return list;
    }

    public static <T extends Indexable> T getIndexable(Map map, String key, Class<T> t) {
        Map map1 = (Map) map.get(key);
        return getIndexable(map1, t);
    }

    public static <T extends Indexable> T getIndexable(Map map, Class<T> t) {
        T instance = IndexUtils.getInstanceIndexable(t);
        return (T) instance.fromIndex((Map) map);
    }

    /**
     * Converts a List of Object T to an List of Map<String, Object> for serialize in the index
     *
     * @param listT
     * @param <T>
     * @return
     */
    public static <T extends Indexable> List<Map<String, Object>> toIndex(List<T> listT) {
        List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
        for (T t : listT) {
            mapList.add(t.toIndex());
        }
        return mapList;
    }
    
    /**
	 * Converts a Map<String, T> to a Map<String, Object> for serialize in the index
	 * @param map
	 * @return
	 */
	public static <T extends Indexable> Map<String, Object> toIndex(Map<String, T> map) {
		Map<String, Object> result = new HashMap<>();
		for (Entry<String, T> entry : map.entrySet()) {
			result.put(entry.getKey(), entry.getValue().toIndex());
		}
		return result;
	}

    public static <T extends Index> T getInstanceIndex(Class<T> clazz) {
        T object = null;
        try {
            object = clazz.newInstance();
        } catch (InstantiationException e) {
            Logger.error("...", e);
        } catch (IllegalAccessException e) {
            Logger.error("...", e);
        }
        return object;
    }

    public static <T extends Indexable> T getInstanceIndexable(Class<T> clazz) {
        T object = null;
        try {
            object = clazz.newInstance();
        } catch (InstantiationException e) {
            Logger.error("...", e);
        } catch (IllegalAccessException e) {
            Logger.error("...", e);
        }
        return object;
    }

    /**
     * Convert String to Object
     *
     * @param value
     * @param targetType
     * @return
     */
    public static Object convertValue(final Object value, final Class<?> targetType) {
        if (value == null) {
            return null;
        }
        if (targetType.equals(value.getClass())) {
            return value;
        }

        if (targetType.equals(String.class)) {
            return value.toString();
        }
        else if (targetType.equals(BigDecimal.class)) {
            return new BigDecimal(value.toString());
        }
        else if (targetType.equals(Date.class)) {
            return convertToDate(value);
        }
        else if (targetType.equals(Integer.class)) {
            if (value instanceof Number) {
                return Integer.valueOf(((Number) value).intValue());
            }
            else {
                return Integer.valueOf(value.toString());
            }
        }
        else if (targetType.equals(Long.class)) {
            if (value instanceof Number) {
                return Long.valueOf(((Number) value).longValue());
            }
            else {
                return Long.valueOf(value.toString());
            }
        }
        else if (targetType.equals(Double.class)) {
            if (value instanceof Number) {
                return Double.valueOf(((Number) value).doubleValue());
            }
            else {
                return Double.valueOf(value.toString());
            }
        }
        else if (targetType.equals(Float.class)) {
            if (value instanceof Number) {
                return Float.valueOf(((Number) value).floatValue());
            }
            else {
                return Float.valueOf(value.toString());
            }
        }
        else if (targetType.equals(UUID.class)) {
            return UUID.fromString((String) value);
        }
        else if (targetType.equals(GeoPoint.class)) {
            Map geoValuesMap = (Map) value;
            return new GeoPoint((Double)geoValuesMap.get("lat"),(Double)geoValuesMap.get("lon"));
        }
        else {
            return value;
        }
    }

    /**
     * Convert to date.
     *
     * @param value the value
     * @return the date
     */
    private static Date convertToDate(Object value) {
        Date date = null;
        if (value != null && !"".equals(value)) {
            if (value instanceof Long) {
                date = new Date(((Long) value).longValue());

            } else if (value instanceof String) {
                String val = (String) value;
                int dateLength = String.valueOf(Long.MAX_VALUE).length();
                if (dateLength == val.length()) {
                    date = new Date(Long.valueOf(val).longValue());
                } else {
                    date = getDate(val);
                }
            } else {
                date = (Date) value;
            }
        }
        return date;
    }

    private static Date getDate(String val) {
        try {
            return XContentBuilder.defaultDatePrinter.parseDateTime(val).toDate();
        } catch (Throwable t) {
            Logger.error(val, t);
        }
        return null;
    }
}

@@ -1492,17 +1492,20 @@
     /**%0A
-%09
+    
  * Conve
@@ -1577,17 +1577,20 @@
 e index%0A
-%09
+    
  * @para
@@ -1595,17 +1595,20 @@
 ram map%0A
-%09
+    
  * @retu
@@ -1614,14 +1614,20 @@
 urn%0A
-%09 */%0A%09
+     */%0A    
 publ
@@ -1708,18 +1708,24 @@
  map) %7B%0A
-%09%09
+        
 Map%3CStri
@@ -1762,18 +1762,24 @@
 ap%3C%3E();%0A
-%09%09
+        
 for (Ent
@@ -1822,11 +1822,20 @@
 ) %7B%0A
-%09%09%09
+            
 resu
@@ -1890,14 +1890,26 @@
 ));%0A
-%09%09%7D%0A%09%09
+        %7D%0A        
 retu
@@ -1923,11 +1923,18 @@
 lt;%0A
-%09%7D%0A
+    %7D%0A    
 %0A   

Reformat code