package com.org.hktshop.utils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import com.org.hktshop.base.BaseModel;


/***
 * resultSet转换器
 * @author mxk
 *
 * @param <T>
 */
public class ObjectMapper<T extends BaseModel> {
	/** 转换的目标对象 */
	private T clazz;
	
	public ObjectMapper(){
		
	}
	
	/** 名称处理器 */
	public ObjectMapper(T clazz) {
		this.clazz = clazz;
	}
	  /**
     * 初始化实例
     * 
     * @param clazz
     * @return
     */
    @SuppressWarnings("unchecked")
	public T newInstance() {
        try {
            return (T) clazz.getClass().newInstance();
        } catch (Exception e) {
			e.printStackTrace();
        }
        return null;
    }
    
	public List<T> ResultSetToObject(ResultSet resultSet) throws SQLException {

		List<String> columns = new ArrayList<>();
		List<T> list = new ArrayList<>();

		Map<String, Method> mapMethod = new Hashtable<>();
		
		Map<String, String> mapField = ClassUtils.getSelfBeanMap(clazz.getClass());
		ResultSetMetaData md = resultSet.getMetaData();

		String columnName = null;
		for (int i = 0; i < md.getColumnCount(); i++) {
			try {
				columnName = md.getColumnLabel(i + 1);
				if(!mapField.containsKey(columnName)) continue;
				
				PropertyDescriptor pd = new PropertyDescriptor(columnName, Class.forName(mapField.get(columnName)));
				mapMethod.put(columnName, pd.getWriteMethod());
				columns.add(columnName);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		while (resultSet.next()) {
			T entity = newInstance();
			for (String cn : columns) {
				try {
					Method writeMethod = mapMethod.get(cn);
					writeMethod.setAccessible(true);
					typeMapper(writeMethod,entity,cn,resultSet);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			list.add(entity);
		}
		return list;
	}
	
	public Map<String,Object> ResultSetToMap(ResultSet resultSet) throws SQLException {
		List<String> columns = new ArrayList<>();
		Map<String,Object> map = new HashMap<>();

		ResultSetMetaData md = resultSet.getMetaData();

		String columnName = null;

		for (int i = 0; i < md.getColumnCount(); i++) {
			try {
				columnName = md.getColumnLabel(i + 1);
				columns.add(columnName);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		//單條數據查詢
		if(resultSet.next()) {
			for (String cn : columns) {
				try {
					Object value = resultSet.getObject(cn);
					map.put(cn, value);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
		return map;
	}
	
	public Object[] ResultSetToArray(ResultSet resultSet) throws SQLException {

		List<String> columns = new ArrayList<>();
		List<Object[]> list = new ArrayList<>();

		ResultSetMetaData md = resultSet.getMetaData();

		String columnName = null;

		for (int i = 0; i < md.getColumnCount(); i++) {
			try {
				columnName = md.getColumnLabel(i + 1);
				
				columns.add(columnName);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		while (resultSet.next()) {
			Object[] val = new Object[md.getColumnCount()];
			int index = 0;
			for (String cn : columns) {
				try {
					Object value = resultSet.getObject(cn);
					if(DateUtil.isValidDate(value)){
						val[index] = DateUtil.formatTime(value);
					}else{
						val[index] = value;
					}
					index++;
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			list.add(val);
		}
		return list.toArray();
	}

	/***
	 * 数据类型包装器
	 * @param writeMethod	方法
	 * @param column	方法属性名
	 * @param rs	结果集
	 * @throws Exception
	 */
	private void typeMapper(Method writeMethod,T entity, String column, ResultSet rs)
			throws Exception {
		String type = (writeMethod.getParameterTypes()[0]).getName();
		if ("java.lang.String".equals(type)) {
			writeMethod.invoke(entity, rs.getString(column));
		} else if ("int".equals(type)) {
			writeMethod.invoke(entity, rs.getInt(column));
		} else if ("java.lang.Integer".equals(type)) {
			writeMethod.invoke(entity, rs.getInt(column));
		} else if ("long".equals(type)) {
			writeMethod.invoke(entity, rs.getLong(column));
		} else if ("java.lang.Long".equals(type)) {
			writeMethod.invoke(entity, rs.getLong(column));
		} else if ("boolean".equals(type) || "java.lang.Boolean".equals(type)) {
			writeMethod.invoke(entity, rs.getBoolean(column));
		} else if ("java.util.Date".equals(type)) {
			writeMethod.invoke(entity, rs.getTimestamp(column));
		} else if ("double".equals(type) || "java.lang.Double".equals(type)) {
			writeMethod.invoke(entity, rs.getDouble(column));
		} else if ("float".equals(type) || "java.lang.Float".equals(type)) {
			writeMethod.invoke(entity, rs.getFloat(column));
		}else if ("BigDecimal".equals(type) || "java.math.BigDecimal".equals(type)) {
			writeMethod.invoke(entity, rs.getBigDecimal(column));
		}
	}
}
