package org.appfuse.util;
import java.beans.PropertyDescriptor;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.ResourceBundle;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.appfuse.model.BaseObject;
public final class ConvertUtil {
    
    private static Log log = LogFactory.getLog(ConvertUtil.class);
    
    
    public static Map convertBundleToMap(ResourceBundle rb) {
        Map map = new HashMap();
        for (Enumeration keys = rb.getKeys(); keys.hasMoreElements();) {
            String key = (String) keys.nextElement();
            map.put(key, rb.getString(key));
        }
        return map;
    }
    
    public static Properties convertBundleToProperties(ResourceBundle rb) {
        Properties props = new Properties();
        for (Enumeration keys = rb.getKeys(); keys.hasMoreElements();) {
            String key = (String) keys.nextElement();
            props.put(key, rb.getString(key));
        }
        return props;
    }
    
    public static Object populateObject(Object obj, ResourceBundle rb) {
        try {
            if (obj == null) {
                obj = obj.getClass().newInstance();
            }
            Map map = convertBundleToMap(rb);
            BeanUtils.copyProperties(obj, map);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("Exception occured populating object: " + e.getMessage());
        }
        return obj;
    }
    
    public static Object convertDates(Object obj, Object form) {
        if (obj == null || form == null) {
            return null;
        }
                PropertyDescriptor[] origDescriptors =
                PropertyUtils.getPropertyDescriptors(obj);
        for (int i = 0; i < origDescriptors.length; i++) {
            String name = origDescriptors[i].getName();
            if (origDescriptors[i].getPropertyType().equals(Date.class)) {
                if (PropertyUtils.isWriteable(form, name)) {
                    try {
                        Date date =
                                (Date) PropertyUtils.getSimpleProperty(obj, name);
                        PropertyUtils.setSimpleProperty(form, name,
                                DateUtil.getDate(date));
                    } catch (Exception e) {
                        log.error("Error converting date from object to form");
                    }
                }
            }
        }
        return form;
    }
    
    public static Object getOpposingObject(Object o) throws ClassNotFoundException,
                                                InstantiationException,
                                                IllegalAccessException {
        String name = o.getClass().getName();
        if (o instanceof BaseObject) {
            if (log.isDebugEnabled()) {
                log.debug("getting form equivalent of pojo...");
            }
            name = StringUtils.replace(name, "model", "webapp.form");
            name += "Form";
        } else {
            if (log.isDebugEnabled()) {
                log.debug("getting pojo equivalent of form...");
            }
            name = StringUtils.replace(name, "webapp.form", "model");
            name = name.substring(0, name.indexOf("Form"));
        }
        Class obj = Class.forName(name);
        if (log.isDebugEnabled()) {
            log.debug("returning className: " + obj.getName());
        }
        return obj.newInstance();
    }
    
    public static Object convert(Object o) throws Exception {
        if (o == null) {
            return null;
        }
        Object target = getOpposingObject(o);
        BeanUtils.copyProperties(target, o);
        return target;
    }
    
    
    public static Object convertLists(Object o) throws Exception {
        if (o == null) {
            return null;
        }
        
        Object target = null;
        
        PropertyDescriptor[] origDescriptors =
                PropertyUtils.getPropertyDescriptors(o);
        for (int i = 0; i < origDescriptors.length; i++) {
            String name = origDescriptors[i].getName();
            if (origDescriptors[i].getPropertyType().equals(List.class)) {
                List list = (List) PropertyUtils.getProperty(o, name);
                for (int j=0; j < list.size(); j++) {
                    Object origin = list.get(j);
                    target = convert(list.get(j));
                    if (!(target instanceof BaseObject)) {
                        target = convertDates(origin, target);
                    }
                    list.set(j, target);
                }
                PropertyUtils.setProperty(o, name, list);
            }
        }
        return o;
    }
}