package com.axiastudio.zoefx.db;

import javafx.beans.property.Property;
import javafx.scene.control.cell.PropertyValueFactory;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * User: tiziano
 * Date: 21/03/14
 * Time: 13:00
 */
public class Model<T> {

    private T entity;
    private Map<String, Property> properties = new HashMap();

    public Model(T entity) {
        this.entity = entity;
        initialize();
    }

    private void initialize(){
        // methods
        for( Method method: entity.getClass().getMethods() ){
            if( method.getName().startsWith("get") ){
                String name = method.getName().substring(3).toLowerCase();
                Property item = createProperty(name, method.getReturnType());
                if( item != null ){
                    properties.put(name, item);
                }
            }
        }
        // fields
        for( Field field: entity.getClass().getFields() ){
            String name = field.getName();
            Property item = createProperty(name, field.getType());
            if( item != null ){
                properties.put(name, item);
            }
        }
    }

    private Property createProperty(String name, Class<?> returnType){
        Property item=null;
        if( returnType == String.class ){
            item = new ItemStringProperty(entity, name);
        } else if( returnType == Boolean.class ){
            item = new ItemBooleanProperty(entity, name);
        } else if( returnType == Date.class ){
            item = new ItemDateProperty(entity, name);
        } else if( returnType.isEnum() ){
            item = new ItemEnumProperty(entity, name);
        } else if( returnType == Collection.class ){
            item = new ItemListProperty(entity, name);
        }
        return item;
    }

    public Property getProperty(String name){
        return properties.get(name);
    }

    public PropertyValueFactory getPropertyValueFactory(String name, String idColumn) {
        try {
            Field field = entity.getClass().getField(name);
            Class klass = classFromCollectionField(field);
            PropertyValueFactory propertyValueFactory = createPropertyValueFactory(klass, String.class, idColumn);
            return propertyValueFactory;
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        return null;
    }

    private <E, S> PropertyValueFactory<E, S> createPropertyValueFactory(Class<E> klassE, Class<S> klassS, String name){
        try {
            Field field = klassE.getField(name);
            //Class klass = classFromCollectionField(field);
            PropertyValueFactory<E, S> propertyValueFactory = new PropertyValueFactory<E, S>(name);
            return propertyValueFactory;
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        return null;
    }

    private Class classFromCollectionField(Field field){
        Type type = field.getGenericType();
        ParameterizedType parameterizedType = (ParameterizedType) type;
        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
        return (Class) actualTypeArguments[0];
    }

    public static Class classFromCollectionMethod(Method method){
        ParameterizedType pt = (ParameterizedType) method.getGenericReturnType();
        Type[] actualTypeArguments = pt.getActualTypeArguments();
        return (Class) actualTypeArguments[0];
    }



}

@@ -440,17 +440,17 @@
 s Model%3C
-T
+E
 %3E %7B%0A%0A   
@@ -458,17 +458,17 @@
 private 
-T
+E
  entity;
@@ -548,17 +548,17 @@
 c Model(
-T
+E
  entity)
@@ -2603,17 +2603,17 @@
 rivate %3C
-E
+T
 , S%3E Pro
@@ -2626,25 +2626,25 @@
 alueFactory%3C
-E
+T
 , S%3E createP
@@ -2669,17 +2669,17 @@
 y(Class%3C
-E
+T
 %3E klassE
@@ -2864,25 +2864,25 @@
 alueFactory%3C
-E
+T
 , S%3E propert
@@ -2922,17 +2922,17 @@
 Factory%3C
-E
+T
 , S%3E(nam

Refactor generic name.